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