By default, PowerShell’s Array is an object class; hence, its length a “fixed size” as an object. Therefore, any pop, splice, or push methods will not work with Array elements in this language as compared to a other languages such as JavaScript and Python. Here are two workarounds to this issue:
- Cast the Array object as a
[System.Collections.ArrayList]$ArrayObject
; which will effectively convert the $ArrayObject to a “ArrayList” class. Hence,$ArrayObject.GetType().Name
will return “ArrayList
“, instead of “Object[]
“. This will make it “mutable” or changeable, whereby methods such as .Add() and .Remove() are available. The only downside to this conversion is that ArrayList cannot be multi-dimensional. Hence, the third item on this list is the catch-all technique in dealing with $ArrayObject ‘s. - Convert $ArrayObject to a $Collection type: $Collection =
{$ArrayObject}.Invoke()
will also create a mutable Collection data type that will expose similar available methods as ArrayList. - Manually filter the Array’s elements against a certain values, then reassign that result to itself. Here are some examples.
# Better Illustration of workaround #3 function validateData{ param($inputData=$sourcesAndDestinations) $objectLength=$inputData.from.length for ($i=0;$i -lt $objectLength; $i++){ $from=$inputData.from[$i] $to=$inputData.to[$i] #"Checking $from and $to ..." #if(!(test-path $from) -OR !(test-path $to) ){ if(!(test-path $to)){ write-host "$to is not reachable." # Remove row if any path doesn't resolve. Overcome limitations of Powershell's immutable array "fixed size" using this workaround $castedArrayList=[System.Collections.ArrayList]$inputData; $castedArrayList.RemoveAt($i); $inputData=[Array]$castedArrayList; #reversed the casting #$inputData.from = $inputData.from|?{$_ -ne $from} #$inputData.to = $inputData.to|?{$_ -ne $to} $objectLength--; $i--; } #else{write-host "$to is reachable."} } return $inputData } $sourcesAndDestinations=validateData -inputData $sourcesAndDestinations
# Illustration of workaround #3 $arr=@{} $arr["from"] = @{}; $arr["to"] = @{} #$arr["from"] = @("C:\Temp\Tech_Documentation"); $arr["to"]=@("\\FILESERVER01\Docs") $arr["from"] += "C:\Temp\Test"; $arr["to"]+="\\FILESERVER01\Test" $arr["from"] += "C:\InvalidDirectory"; $arr["to"]+="\\FILESERVER01\Void" function sanitizeObject{ param($GLOBAL:object=$arr) $objectLength=$object.from.count for ($i=0;$i -lt $objectLength; $i++){ $from=$object.from[$i] $to=$object.to[$i] #"Checking $from and $to ..." if(!(test-path $from) -OR !(test-path $to) ){ # Remove row if any path doesn't resolve. Overcome limitation of Powershell's immutable array "fixed size" #"Removing $($object.from[$i]) and $($object.to[$i]) ..." $object.from = $object.from|?{$_ -ne $from} $object.to = $object.to|?{$_ -ne $to} # Decrement object length pointer value to reflect new length and readjust index number $objectLength--; $i--; } } return $object } $arr=sanitizeObject -object $arr
Categories: