5

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:

  1. 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.
  2. 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] | %{$_}

2 Answers 2

5

You can simply use a plus operator:

$array = @('bar', 'baz')
$array = @('foo') + $array

Note: this re-creates actually creates a new array instead of changing the existing one (but the $head, $tail = $array way of shifting you refer to works extactly in the same way).

Sign up to request clarification or add additional context in comments.

Comments

4

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

1 Comment

I like. Ultimately, I need to proactively create the empty array before I can add items to it. Making it an ArrayList means that my code is a little more readable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.