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)
}
}
Matthew
  • 1,412
  • 2
  • 20
  • 35
tester81
  • 533
  • 2
  • 9
  • 28

2 Answers2

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} | ...
iRon
  • 20,463
  • 10
  • 53
  • 79
  • Its not about the Pipelins, pls read my description, I was asking about removing objects from the objects array. – tester81 Sep 06 '19 at 15:04
  • Yes, I have read that, for several reasons, I am just recommending you to use the pipelines for huge files. – iRon Sep 06 '19 at 15:08
  • 1
    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](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7.1) and the LHS is not scalar, it filters the list by the test – ninMonkey Nov 22 '20 at 22:41
  • @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). – iRon Nov 23 '20 at 08:09
  • See also: [the performance of a complete (PowerShell) solution is supposed to be better than the sum of its parts](https://stackoverflow.com/a/59437162/1701026) – iRon Nov 23 '20 at 08:10
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)
}
}
Jeff Zeitlin
  • 9,773
  • 2
  • 21
  • 33
  • The official docs say you should replace `ArrayList` with a `List` for better performance (and other reasons) https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-5.0#remarks – ninMonkey Nov 22 '20 at 22:37
  • @ninMonkey - I've not found any way to use parameterized classes (e.g., List) in PowerShell. – Jeff Zeitlin Nov 23 '20 at 12:06
  • 1
    it's `[list[t]]` --- `using namespace System.Collections.Generic;` `$numbers = [list[int]]::new()` `$numbers.Add(40)` – ninMonkey Jan 23 '21 at 19:25