Home > Software design >  How to get the "difference" between two objects in another object with the same structure
How to get the "difference" between two objects in another object with the same structure

Time:06-29

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.

CodePudding user response:

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

$CustomObject1 | Where-Object {$_.id -notin $CustomObject2.id}

CodePudding user response:

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.

CodePudding user response:

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.

  • Related