Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering list with another list PowerShell

Coming from a C# background and being a complete PowerShell novice, I am trying to make a simple filtering based on two lists/arrays.

Goal: filter elements of list 'toFilter' based on list 'filter', so to only keep elements of 'toFilter', which are matching at least one of the patterns listed in 'filter'.

Ideally I would like to achieve that using piping or Linq (and not nested loops).

In C#, I would do it like this:

string[] filter  = {"A", "B", "C"};
string[] toFilter = {"AA", "AB", "DD"};

var filtered = toFilter.Where(s1 => filter.Any(s2 => s1.Contains(s2))).ToList();

or even shorther, using method groups:

var filtered = toFilter.Where(s1 => filter.Any(s1.Contains)).ToList();

With the expected outcome of:

AA AB

For Powershell, I found an article which describes powershell equivalents of Linq in C#, but apparently I cannot grasp the syntax.

I came with a following solution:

$filter = @("A", "B", "C")
$toFilter = @("AA", "AB", "DD")

$filtered = $toFilter | where {[Linq.Enumerable]::Any([string[]]$filter, [Func[string,bool]]{ $_ -match $args[0] })}

But it results in an empty list.

What would be a correct way of using those two arrays to come with an expected result?

EDIT: Apparently my solution works, but it is not pure LINQ, so a question is still valid.

like image 688
sirVir Avatar asked Feb 18 '26 10:02

sirVir


2 Answers

The reason your example fails is that $_ and $args[0] refer to the same thing in the inner delegate.

There's no need to employ LINQ here though - you can do the same with a nested Where-Object clause:

$filter = @("A", "B", "C")
$toFilter = @("AA", "AB", "DD")

$filtered = $toFilter | Where-Object {
    $item = $_
    @($filter |Where-Object {$item.Contains($_)}).Count -gt 0
}
like image 57
Mathias R. Jessen Avatar answered Feb 20 '26 00:02

Mathias R. Jessen


Cards on the table this is my first day working with LINQ. It seems like something I would like to be able to use. I tried to nest LINQ statements as best I could to try and get the right results using only LINQ.

[Linq.Enumerable]::where(
    $toFilter,
    [System.Func[System.Object,bool]]{ 
        param($filterItem)
        [Linq.Enumerable]::Any(
            $filter, 
            [Func[System.Object,bool]]{
                param($singlefilter) 
                # write-host "$filterItem -match $singlefilter"
                $filterItem -match $singlefilter}
        )
    }
)

Where to work over $toFilter and the Any checks each $filter against each $toFilter item.

like image 33
Matt Avatar answered Feb 20 '26 00:02

Matt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!