question

DenisPasternak-3587 avatar image
0 Votes"
DenisPasternak-3587 asked AndreasBaumgarten commented

Check if an strings of list exists in other list

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-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered RichMatheisen-8856 edited

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


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BillStewart avatar image
0 Votes"
BillStewart answered DenisPasternak-3587 commented

What are you expecting $list -contains $filterList to do?

Are you asking if $list contains all members in $filterList, or are you asking if $list contains any of the members in $filterList?

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sorry:
if $list contains any of the members in $filterList

0 Votes 0 ·
DenisPasternak-3587 avatar image
0 Votes"
DenisPasternak-3587 answered DenisPasternak-3587 edited

Sorry, the question:
I want to get True if $list containe any string in $filterList

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AndreasBaumgarten avatar image
1 Vote"
AndreasBaumgarten answered AndreasBaumgarten edited

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
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sorry, but I don't need to compare. I need to find an object in array.
The expression will be more complex, this is just an example. All I want is to shorten the line.

Thank you.

0 Votes 0 ·
RichMatheisen-8856 avatar image
1 Vote"
RichMatheisen-8856 answered RichMatheisen-8856 commented

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"
 }


· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi Rich,

may I ask you what is the difference between your approach and my approach (beside the fact your are building $a as an array)?

Please don't get me wrong: I am still learning and like to improve my PowerShell approaches! This is no criticism or something else!

Kind regards
Andreas Baumgarten

0 Votes 0 ·

I tried to answer this in a comment, but I don't think comments like more than a few lines of code, so I added another answer.

0 Votes 0 ·
BillStewart avatar image
1 Vote"
BillStewart answered

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.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
1 Vote"
RichMatheisen-8856 answered AndreasBaumgarten commented

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
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you!


Kind regards
Andreas

0 Votes 0 ·
DenisPasternak-3587 avatar image
0 Votes"
DenisPasternak-3587 answered DenisPasternak-3587 edited

Thank you.

The question:

How I can make more this shortly ?

( ($list -contains '50') -or ($list -contains '20') -or ($list -contains '60') -or ($list -contains '1') -or ($list -contains '2') -or ($list -contains '3') -or ($list -contains '4') -or ($list -contains 'any') ) -and ($list -notcontains '777')





5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.