Jason V
Jason V

Reputation: 905

PowerShell: Filtering an array by another [filter] array if any part of the text matches.

Okay, I'm still fairly new to PowerShell.

I've written a piece of code that works, but it smells entirely wrong. What is the right way to write this from a PowerShell standpoint?

$filters = @("*a*","*b*")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

Write-Host "Filters" -ForegroundColor Yellow
$filters 
Write-Host "Data" -ForegroundColor Yellow
$data

$results = @()

foreach ($d in $data)
{
    [bool] $skip = $false
    foreach ($filter in $filters)
    {
        if ($d -like $filter)
        {
            $skip = $true
        }
    }

    if ($skip -eq $false)
    {
        $results += $d
    }
}

Write-Host "Desired Results" -ForegroundColor Yellow
$desiredResults
Write-Host "Results" -ForegroundColor Yellow
$results

Upvotes: 2

Views: 5759

Answers (5)

Paul
Paul

Reputation: 11

I frequently have problems with double pipelines so I switch one to ForEach.
Here is a one-liner.

$filters = @("*a*","*b*")
$data = @("c/a","c/b","c/a/d","e","a","e/f")

ForEach ($Item in $data) { If ( !($filters | Where-Object {$Item -like $_})) { $Item } }

Upvotes: 1

Esperento57
Esperento57

Reputation: 17472

try this

$data | %{$val=$_; $Nb=($filters | where {$val -like $_}).Count ; if ($Nb -eq 0) {$val} }

Upvotes: 0

Chandan Rai
Chandan Rai

Reputation: 10369

you can do like this

$filters = @("a","b")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

$data | Select-String -Pattern $filters -NotMatch

Upvotes: 6

TheMadTechnician
TheMadTechnician

Reputation: 36297

The right way? I don't know that there is a right way. I can give you what I consider a better way using RegEx:

$filters = @("a","b")
$data = @("c/a","c/b","c/a/d","e","a","e/f")
$desiredResults = @("e","e/f")

$RegExFilter = ($Filters|%{[regex]::escape($_)}) -join '|'

$Results = $data | Where{$_ -notmatch $RegExFilter}

Write-Host "Desired Results" -ForegroundColor Yellow
$desiredResults
Write-Host "Results" -ForegroundColor Yellow
$results

This basically takes each element of the $filters array, performs a regex escape on it to escape any special characters, and then joins all of those results with a pipe character. So in the example given $RegExFilter equals a|b. Then it filters $data against anything that matches that pattern.

Upvotes: 2

4c74356b41
4c74356b41

Reputation: 72171

The only real problem here - is you have to compare string to and array of strings, which I don't think powershell can do elegantly (but I might be wrong), so I've done this:

foreach ($d in $data)
{
    if ($d -notlike $filters[0] -and $d -notlike $filters[1])
    {
        $results += $d
    }
}

I assume the syntaxis is clean enough and doesn't need any explanation. if it needs explanation, tell me in comments.

Upvotes: 0

Related Questions