1

I have a huge pscustomobject Array1, and a second smaller Array2 containing text/strings. I want to remove objects from Array1 which have specific status in Array2. For example, remove from Array1 all elements with Array2.object.status = "Removed".

I don't want to create another Objects array using -contains or -notcontains. I know how to do it but I am looking for something more sophisticated, I was trying to convert my arrays to --> [System.Collections.ArrayList], like here --> $Array = [System.Collections.ArrayList]$Array. I tried to use "Remove" and "RemoveAt" methods but still getting the same error

Error:

 Exception calling "Remove" with "1" argument(s): "Collection was of a fixed size.

Below please find extract from my code:

$Array1 = [System.Collections.ArrayList]$Array1 
$Array1 = obj1, obj2, obj3 #contains pscustomobjects, with multiple 
properties
$Array2 = text1, text2, text3 #contains status names, only strings/text

foreach ($element in $Array1) {
if ($Array2 -contains $element.status) {
$Array1.Remove($element)
}
}

2 Answers 2

1

This is actually not the philosophy behind PowerShell which is best in using pipelines (see: understanding pipelines especially when using huge PSCustomObject arrays. Meaning that you should leave the array intact and filter the concerned objects on the fly with the Where-Object, like:

$Array1 | Where-Object {$Array2 -Contains $_.status} | ...
Sign up to request clarification or add additional context in comments.

5 Comments

Its not about the Pipelins, pls read my description, I was asking about removing objects from the objects array.
Yes, I have read that, for several reasons, I am just recommending you to use the pipelines for huge files.
For the non-pipeline version you can remove items from an array using $array = 'a', 'b', 'c'; $array -ne 'b' which removes b -- when using comparison operators and the LHS is not scalar, it filters the list by the test
@ninMonkey, yes, that is the semantic PowerShell way to do this. Note that it is similar to -contains or -notcontains except that it does a literal (not)match. Besides, it also uses the pipeline for output which is by fact PowerShell's nature but often dismissed (and under estimated) by C# programmers as "not sophisticated". Arrays are mutual, which means you have to translate into e.g. a ArrayList where you create an extra step and lose performance and the easy PowerShell syntax (unless you can combine this with another part of the solution).
0

It is likely that your problem is that $Array1 is no longer a [System.Collections.ArrayList]; you're assigning to it with = and a comma list of objects. Instead, try using

$Array1 = [System.Collections.ArrayList]$Array1 
# Not this...
# $Array1 = obj1, obj2, obj3 #contains pscustomobjects, with multiple properties

# This, instead...
(obj1, obj2, obj3) | ForEach-Object { $Array1.Add($_) }

$Array2 = text1, text2, text3 #contains status names, only strings/text

foreach ($element in $Array1) {
if ($Array2 -contains $element.status) {
$Array1.Remove($element)
}
}

You might also be able to do

[System.Collections.ArrayList]$Array1 = obj1, obj2, obj3
# Not this...
# $Array1 = obj1, obj2, obj3 #contains pscustomobjects, with multiple properties

$Array2 = text1, text2, text3 #contains status names, only strings/text

foreach ($element in $Array1) {
if ($Array2 -contains $element.status) {
$Array1.Remove($element)
}
}

3 Comments

The official docs say you should replace ArrayList with a List for better performance (and other reasons) learn.microsoft.com/en-us/dotnet/api/…
@ninMonkey - I've not found any way to use parameterized classes (e.g., List<T>) in PowerShell.
it's [list[t]] --- using namespace System.Collections.Generic; $numbers = [list[int]]::new() $numbers.Add(40)

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.