Llaslo
Llaslo

Reputation: 345

Only Add to Array if it doesn't exist

In PowerShell v2, I'm trying to add only unique values to an array. I've tried using an if statement that says, roughly, If (-not $Array -contains 'SomeValue'), then add the value, but this only ever works the first time. I've put a simple code snippet that shows what I'm doing that doesn't work and what I've done as a workaround that does work. Can someone please let me know where my issue is?

Clear-Host
$Words = @('Hello', 'World', 'Hello')

# This will not work
$IncorrectArray = @()
ForEach ($Word in $Words)
{
    If (-not $IncorrectArray -contains $Word)
    {
        $IncorrectArray += $Word
    }
}

Write-Host ('IncorrectArray Count: ' + $IncorrectArray.Length)

# This works as expected
$CorrectArray = @()
ForEach ($Word in $Words)
{
    If ($CorrectArray -contains $Word)
    {
    }
    Else
    {
        $CorrectArray += $Word
    }
}

Write-Host ('CorrectArray Count: ' + $CorrectArray.Length)

The Result of the first method is an array containing only one value: "Hello". The second Method contains two values: "Hello" & "World". Any help is greatly appreciated.

Upvotes: 16

Views: 61650

Answers (2)

dugas
dugas

Reputation: 12493

The first time around, you evaluate -not against an empty array, which returns true, which evaluates to: ($true -contains 'AnyNonEmptyString') which is true, so it adds to the array. The second time around, you evaluate -not against a non-empty array, which returns false, which evaluates to: ($false -contains 'AnyNonEmptyString') which is false, so it doesn't add to the array.

Try breaking your conditions down to see the problem:

$IncorrectArray = @()
$x = (-not $IncorrectArray) # Returns true
Write-Host "X is $x"
$x -contains 'hello' # Returns true

then add an element to the array:

$IncorrectArray += 'hello'
$x = (-not $IncorrectArray) # Returns false
    Write-Host "X is $x"
$x -contains 'hello' # Returns false

See the problem? Your current syntax does not express the logic you desire.

You can use the notcontains operator:

Clear-Host
$Words = @('Hello', 'World', 'Hello')

# This will work
$IncorrectArray = @()
ForEach ($Word in $Words)
{
  If ($IncorrectArray -notcontains $Word)
  {
    $IncorrectArray += $Word
  }
}

Upvotes: 9

Frode F.
Frode F.

Reputation: 54981

To fix your code, try -notcontains or at least WRAP your contains-test in parantheses. Atm. your test reads:

If "NOT array"(if array doens't exist) contains word.

This makes no sense. What you want is:

If array does not contain word..

That's written like this:

If (-not ($IncorrectArray -contains $Word))

-notcontains is even better, as @dugas suggested.

Upvotes: 17

Related Questions