1

Is there a non for-loop way to remove some items from a arrayList?

$remotesumerrors = $remoteFiles | Select-String  -Pattern '^[a-f0-9]{32}(  )' -NotMatch

I want to remove the output of the above from the $remoteFiles var.. is there some pipe way to remove them?

Tony
  • 8,681
  • 7
  • 36
  • 55

4 Answers4

1

Assuming all of the following:

  • you do need the results captured in $remotesumerrors separately
  • that $remoteFiles is a collection of System.IO.FileInfo instances, as output by Get-ChildItem, for instance
  • it is acceptable to save the result as an invariably new collection back to $remoteFiles,

you can use the .Where() array method as follows (this outperforms a pipeline-based solution based on the Where-Object cmdlet):

# Get the distinct set of the full paths of the files of origin
# from the Select-String results stored in $remotesumerrors
# as a hash set, which allows efficient lookup.
$errorFilePaths = 
  [System.Collections.Generic.HashSet[string]] $remotesumerrors.Path

# Get those file-info objects from $remoteFiles
# whose paths aren't in the list of the paths obtained above.
$remoteFiles = $remoteFiles.Where({ -not $errorFilePaths.Contains($_.FullName) })

As an aside:

  • Casting a collection to [System.Collections.Generic.HashSet[T]] is a fast and convenient way to get a set of distinct values (duplicates removed), but note that the resulting hash set's elements are invariably unordered and that, with strings, lookups are by default case-sensitive - see this answer for more information.
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

If it truly was a [collections.arraylist], you could remove an element by value. There's also .RemoveAt(), to remove by array index.

[System.Collections.ArrayList]$array = 'a','b','c','d','e'


$array.remove

OverloadDefinitions
-------------------
void Remove(System.Object obj)
void IList.Remove(System.Object value)


$array.remove('c')
$array

a
b
d
e
js2010
  • 23,033
  • 6
  • 64
  • 66
0

Use the Where-Object cmdlet to filter the list:

$remoteFiles = $remoteFiles |Where-Object { $_ |Select-String -Pattern '^[a-f0-9]{32}(  )' -NotMatch }
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • hmm they all still seem to be in the remoteFiles var ... – Tony Oct 27 '21 at 17:48
  • Nice, though I suggest adding `-Quiet` to optimize the `Select-String` call. Also worth nothing that the result will be an _array_ (or singe file-info object) - though perhaps @Tony actually meant an array when referring to "arrayList" rather than a [`System.Collections.ArrayList`](https://learn.microsoft.com/en-US/dotnet/api/System.Collections.ArrayList) instance, specifically. – mklement0 Oct 27 '21 at 18:20
  • oh how do I do that where with -ne ? – Tony Oct 27 '21 at 18:24
  • It might just be a typo, but be aware that if you implement the filter like you did with your original code sample i.e ( $remotesumerrors = $remoteFiles | etc. } $remoteFiles will remain unchanged because the new filtered arraylist is being saved to "$remotesumerrors". You'd have to use the same variable name like mathias did in his answer above. – diopside Oct 27 '21 at 18:31
  • no I obvi changed the var names - but looks like my new remoteFiles var contains ONLY the errors vs I want the opposite. – Tony Oct 27 '21 at 18:39
  • 2
    @Tony: `Where-Object { -not ($_ |Select-String -Quiet -NotMatch -Pattern '^[a-f0-9]{32}( )') }` – mklement0 Oct 27 '21 at 18:45
  • @tony Please output $remoteFiles and paste the results here – Aaron Oct 28 '21 at 02:09
0

Let assume that $remoteFiles is a file object of type System.IO.FileInfo. I also assume that you want to filter based on filename.

$remotesumerrors = $remoteFiles.name | Select-String  -Pattern '^[a-f0-9]{32}' -NotMatch

What are trying to do with "( )" or what is query that you want to do.

edit: corrected answer based on comment

Aaron
  • 563
  • 3
  • 13
  • [a-f0-9] is totally valid. So is [a-f][0-9]. But they are doing diff things. First one only matches a single character that could be any letter a - f or any num 0-9, your version matches two adjacent characters where the first is a-f and the second is a num 0-9 – diopside Oct 28 '21 at 01:57
  • @diopside I will give you that but what is "( )". – Aaron Oct 28 '21 at 01:58
  • that's a good question. im not sure in this context. ive used something like that in a regex split operation to shift/pad the resulting list based on the presence of spaces in the string, but not sure what its doing here. Ive only used the select-string cmd once so i need to read up on it – diopside Oct 28 '21 at 02:01