Home > Enterprise >  When does -Contains not work and/or should I use something else
When does -Contains not work and/or should I use something else

Time:02-19

If I have two arrays of information. One massive and the other much smaller.

$lista ="1,2,3,4,5...etc for a lot "
$listb ="1,9,11"  (Much smaller)

If ($listA -contains $listB){
Do stuff
}

Does this make sense and work?

It seems to me like it doesn't always work and I am having trouble double checking it.

CodePudding user response:

Containment Operators are ideal for your use case, however, you're trying to compare an array against another array and that wouldn't work, these operators can help you identify if an element (a scalar, single value) exists in an array.

Both pairs (-in / -notin) and (-contains / -notcontains) should be equally efficient, the only difference is where the scalar is placed, for the first pair the scalar is on the left-hand side of the operation whereas for the later the scalar is on the right-hand side.

Taken from the Docs to helps us give some perspective to the explanation:

<Collection> -contains <Test-object>
<Collection> -notcontains <Test-object>
<Test-object> -in <Collection>
<Test-object> -notin <Collection>

As for your current code, that would require a loop, likely over the small array. Why?

These operators stop comparing as soon as they detect the first match, whereas the equality operators evaluate all input members. In a very large collection, these operators return quicker than the equality operators.

Following that logic, you could loop over your small array and add the comparison, this is up to you which one is more readable for you. Your code could look like this:

$lista = 1,2,3,4,5,6,7,8,9,10
$listb = 2,4,6,8,10

foreach($item in $listb)
{
    if($item -in $lista) {
        $item
        # Do something here
    }
}

There might be use cases where a HashSet<T> can be very useful, for example, if we want to get unique values out of $lista (in this case, we want case-insensitive hence the use of out of StringComparer.OrdinalIgnoreCase Property on it's constructor) and see which values are also contained on $listb, in this case probably we would want to use the .Contains(..) method of this class instead of the operators.

$lista = 'A','x','y','z','a','B','b','C','c'
$listb = 'a','B','c'

$hashset = [System.Collections.Generic.HashSet[string]]::new(
    [string[]]$lista,
    [System.StringComparer]::OrdinalIgnoreCase
)

foreach($item in $listb)
{
    if($hashset.Contains($item)) {
        $item
    }
}
  • Related