Foreach + If function in Powershell not properly removing items from array

25 views Asked by At

I'm a complete beginner with PS, so please go easy on me. I am trying to write a section of code that removes an entire element from the array if it contains a certain pattern (in this case, 'Apple' and 'Banana').

I wrote the code below as a placeholder for the actual data so I can get a better idea of what's going on. The first iteration removes the proper item, but after that it gets a little confused. Where did I go wrong?

$Text = @("Apple and Orange", "Pear and Grape", "Peach and Mango", "Avocado and Banana")
$x = 0

$NotItem = "Banana"
$NoSales = "Apple"

cls
foreach ($element in $Text)
    {
    # Remove elemets from array that don't contain purchasable items
    if ($element -contains $NotItem -or $element -match $NoSales)
        {
        $Text[$x] = $null
        $Next = $Text[$x]
        Write-Host "Condition Met. $element, Step $x, `n`n`    Current Array: $Text`n`n`    Next Item: $Next`n`n"
        }
    # If neither applies, move on
    else 
        {
        $x = $x + 1
        $Next = $Text[$x]
        Write-Host "Condition Not Met. $element, Step $x, `n`n`    Current Array: $Text`n`n`    Next Item: $Next`n`n"
        }
    }

And here's what the output looks like:

Condition Met. Apple and Orange, Step 0, 

    Current Array:  Pear and Grape Peach and Mango Avocado and Banana

    Next Item: 


Condition Not Met. Pear and Grape, Step 1, 

    Current Array:  Pear and Grape Peach and Mango Avocado and Banana

    Next Item: Pear and Grape


Condition Not Met. Peach and Mango, Step 2, 

    Current Array:  Pear and Grape Peach and Mango Avocado and Banana

    Next Item: Peach and Mango


Condition Not Met. Avocado and Banana, Step 3, 

    Current Array:  Pear and Grape Peach and Mango Avocado and Banana

    Next Item: Avocado and Banana
1

There are 1 answers

0
Santiago Squarzon On

I assume you were expecting 'Avocado and Banana' to not be in $Text after running your code, for this you would also use -match instead of -contains which looks for an exact match in a collection. However, by mutating your $Text array you would end up with $null values in it which most likely you do not want, it's better to recreate the array in this case:

$Text = @('Apple and Orange', 'Pear and Grape', 'Peach and Mango', 'Avocado and Banana')
$x = 1

$NotItem = 'Banana'
$NoSales = 'Apple'
$newText = foreach ($element in $Text) {
    # Remove elemets from array that don't contain purchasable items
    $Next = $Text[$x++]
    if ($element -match $NotItem -or $element -match $NoSales) {
        Write-Host "Condition Met. $element, Step $x, Next Item: $Next"
    }
    # If neither applies, move on
    else {
        $element
        Write-Host "Condition Not Met. $element, Step $x, Next Item: $Next"
    }
}

$newText

The simplified approach, using Where-Object for filtering would be:

$newText = $Text | Where-Object { $_ -notmatch $NotItem -or $_ -notmatch $NoSales }