Check if an strings of list exists in other list

Mountain Pond 1,576 Reputation points
2020-11-19T21:42:13.627+00:00

Hi,

I want to find object it array using where-object. But I don't want to use long filter for this.

For Example:

$list = '10','20','30','40'
($list -contains '50') -or ($list -contains '20') -or ($list -contains '60')
True

But it will be false in this cases:

$list = '10','20','30','40'
$filterList = '50','20','60'
($list -contains $filterList)
False

$list = '10','20','30','40'
$filterList = '50','20','60'
($list -in $filterList)
False

How can I reduce the number of comparison operators like "-or" or "-and" in this condition?

Windows for business Windows Server User experience PowerShell
0 comments No comments
{count} votes

Accepted answer
  1. Rich Matheisen 47,901 Reputation points
    2020-11-20T03:43:24.75+00:00

    This isn't shorter in the sense that there's less code, but it might run faster and it doesn't require writing out each condition.

    BTW, you can make the code you posted run a bit faster by moving the test for '777' to the front of the list E.g., if ($list -contains '777' -and (($list -contains '50') -or . . .))

    $ReferenceList = '50', '20', '60', '1', '2', '3', '4', 'any'
    $ListToBeChecked = '0','3','6','9','12','15','18','21','24','27','30','33','36','39'
    if ($ListToBeChecked -contains '777'){
        $Pass = $False
    }
    Else{
        $Pass = $false
        ForEach($v in $ReferenceList){
            if ($ListToBeChecked -contains $v){
                $Pass = $true
                break
            }
        }
    }
    $Pass
    
    0 comments No comments

7 additional answers

Sort by: Most helpful
  1. Andreas Baumgarten 123.4K Reputation points MVP Volunteer Moderator
    2020-11-19T21:58:31.207+00:00

    Maybe this helps:

    $list = '10','20','30','40'
    $filterList = '50','20','60'
    Compare-Object -Referenceobject $list -DifferenceObject $filterlist -IncludeEqual
    

    SideIndicators:
    == Value is in both objects
    => Value is in the DifferenceObject but not in the ReferenceObject
    <= Value is in the ReferenceObject but not in the DifferenceObject

    It's possible to filter the result "value is in both lists":

    $list = '10','20','30','40'
    $filterList = '50','20','60'
    $compareResult = Compare-Object -Referenceobject $list -DifferenceObject $filterlist -IncludeEqual | Where-Object{$_.sideIndicator -eq "=="}
    if ($compareResult) {$compareResult = $true}
    else {$compareResult = $false}
    $compareResult
    

    (If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

    Regards
    Andreas Baumgarten

    1 person found this answer helpful.

  2. Rich Matheisen 47,901 Reputation points
    2020-11-19T22:20:26.787+00:00

    I agree with AndreasBaumgarten's answer, but I'll build a little bit on it:

    $RefList = '10','20','30','40'
    $DiffFilterList = '50','20','60'
    if (([array]$x = Compare-Object -Referenceobject $Reflist -DifferenceObject $DiffFilterlist  -excludedifferent -IncludeEqual).count -gt 0){
        "Items in `$DiffFilterList that are in `$RefList"
        $x.InputObject
    }
    else{
        "Nothing in `$DiffFilterList was found in `$RefList"
    }
    
    1 person found this answer helpful.

  3. Bill Stewart 186 Reputation points
    2020-11-19T22:40:04.523+00:00

    Here's another approach:

    function Compare-ListContainsAny {
      # outputs $true if $list1 contains any item in $list2
      param(
        $list1,
        $list2
      )
      foreach ( $item in $list2 ) {
        if ( $list1 -contains $item ) {
          return $true        
        }
      }
      return $false
    }
    

    With this function defined, Compare-ListContainsAny $list $filterList would output $true.

    1 person found this answer helpful.
    0 comments No comments

  4. Rich Matheisen 47,901 Reputation points
    2020-11-20T00:12:20.157+00:00

    I don't reject or object to criticism, and I certainly don't take your question as criticism in any case.

    Your code certainly answered the OP's requirement of providing a true/false answer. Mine just identified which items produced the result.

    However (since you asked), if the number of elements in the reference array is very large, the Compare-Object can be very slow because it searches from the beginning of the reference array. If that's the case I'd probably not use the PowerShell [array] to define that reference list, but use a .Net class that allowed for the use of a binary search. It's a bit more work, and the object types being compared have to be the same, but it's much faster!

    [System.Collections.ArrayList]$RefList = '10','20','30','40'
    $DiffFilterList = '50','20','60'
    $Found = @()
    $DiffFilterList |
        ForEach-Object{
            if ($RefList.BinarySearch($_) -gt -1){
                $Found += $_
            }
        }
    if ($Found.Count -gt 0){
        "Found: $($Found)"
    }
    else {
        "Didn't find any matches"
    }
    
    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.