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().Namewill 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: