1

TL;DR: This but in powershell
I'm trying to get the "difference" between a list1 and a list2 where list2 is just a sub-set of list1. (or list1 is a super-set of list2).

Keep in mind that this is not the 'real scenario' but the structures of both objects are the same as this:

#List of all the IDs
$list1='2','5','6','11'
$CustObject1=foreach($i in $list1){
    [pscustomobject]@{
        id=$i
    }
}
#Another list, where invalid IDs are not listed
$list2='2','5'
$CustObject2=foreach($i in $list2){
    [pscustomobject]@{
        id=$i
    }
}
#I am looking for $CustObject3 = {id = '6',id = '11'}

Now, I want to create a new "object" that contains a list of all the 'invalid' IDs, in our example the $CustObject3 would contain just id's '6','11'. The reason behind this is because I have a list of 3000 ids that are "valid" and just a couple that are "invalid" (at most 10).
I've tried a lot of options but I can't get it to work, used "where", used double foreach loops, honestly I'm just frustrated at this point but I did try to make it work.

Is this feasible?

Thanks.

francisco.l
  • 306
  • 1
  • 12

3 Answers3

2

You can use the -notin or -notcontains operators to perform the check.

#List of all the IDs
$list1='2','5','6','11'
$CustObject1=foreach($i in $list){
    [pscustomobject]@{
        id=$i
    }
}
#Another list, where invalid IDs are not listed
$list2='2','5'
$CustObject2=foreach($i in $list){
    [pscustomobject]@{
        id=$i
    }
}

$CustObject1 | Where-Object {$_.id -notin $CustObject2.id}
TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
1

Unpack the ids from the PSCustomObjects, put them in HashSets, and then do ExceptWith():

$Ids      = [Collections.Generic.HashSet[string]]::new([string[]]$CustObject1.id)
$validIds = [Collections.Generic.HashSet[string]]::new([string[]]$CustObject2.id)

$Ids.ExceptWith($validIds)

Here $Ids starts with all the Ids, then removes the valid ones. It's updated internally and ends with only the invalid ones.

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
0

Another option is to use the Compare-Object cmdlet:

$CustObject3 = 
  Compare-Object -Property id -PassThru $CustObject1 $CustObject2 | 
  Select-Object * -Exclude SideIndicator

Note:

  • Compare-Object decorates the passed-through objects with a .SideIndicator property indicating which of the input collections a given object is unique to (<= for objects unique to the first collection, => for those unique to the second).

  • Since this information is not of interest here (all result objects are by definition unique to the first collection), Select-Object * -Exclude SideIndicator then removes this extra property.

mklement0
  • 382,024
  • 64
  • 607
  • 775