PowerShell array unshift

arrays, powershell

Solution

You might want to use ArrayList objects instead, as they support insertions at arbitrary locations. For example:

# C:\> $a = [System.Collections.ArrayList]@(1,2,3,4)
# C:\> $a.insert(0,6)
# C:\> $a
6
1
2
3
4

Problem

After reading this helpful article on the Windows PowerShell Blog, I realized I could "shift" off the first part of an array, but didn't know how to "unshift" or push elements onto the front of an array in PowerShell. I am creating an array of hash objects, with the last read item pushed onto the array first. I'm wondering if there is a better way to accomplish this. ``` ## Create a list of files for this collection, pushing item on top of all other items if ($csvfiles[$collname]) { $csvfiles[$collname] = @{ repdate = $date; fileobj = $csv }, $csvfiles[$collname] | %{$_} } else { $csvfiles[$collname] = @{ repdate = $date; fileobj = $csv } } ``` A couple of things to note: - I need to unroll the previous array element with a foreach loop %{$_}, because merely referencing the array would create a nested array structure. I have to have all the elements at the same level. - I need to differentiate between an empty array and one that contains elements. If I attempt to unroll an empty array, it places a $null element at the end of the array. Thoughts? PS: The reason the empty hash element produces a NULL value is that $null is treated as a scalar in PowerShell. For details, see https://connect.microsoft.com/PowerShell/feedback/details/281908/foreach-should-not-execute-the-loop-body-for-a-scalar-value-of-null. ANSWER: Looks like the best solution is to pre-create the empty array when necessary, rather than code around the $null issue. Here's the rewrite using a .NET ArrayList and a native PoSh array. ``` if (!$csvfiles.ContainsKey($collname)) { $csvfiles[$collname] = [System.Collections.ArrayList]@() } $csvfiles[$collname].insert(0, @{ repdate = $repdate; fileobj = $csv }) ## NATIVE POSH SOLUTION... if (!$csvfiles.ContainsKey($collname)) { $csvfiles[$collname] = @() } $csvfiles[$collname] = @{ repdate = $repdate; fileobj = $csv }, ` $csvfiles[$collname] | %{$_} ```

Original source