Array subtraction in PowerShell

Viewed 6864

I have an array of objects:

$people= @()
foreach ($person in $databaseOfGuests)
{
   $people += @{ "FirstName"=$person.FirstName; "LastName"=$person.LastName } 
}

Now I want to remove duplicates from $people, is it possible to do this in PowerShell? Something like:

$people = $people | Select -Uniq

I have two arrays $people1 and $people2, I need to get array of all people that are in $people1 but not in the $people2 and vise versa. Something like:

$peopleInPeople1ButNotInPeople2 = $people1.Substruct($people2)
$peopleInPeople2ButNotInPeople1 = $people2.Substruct($people1)

Is it possible to do it in one line in PS?

4 Answers

Try this:

$people1 | ? {$_ -notin $people2}

or you can filter by property, like firstname or lastname:

$people1 | ? {$_.Firstname -notin $people2.Firstname}
  • the -notin operator is available on PS3 and above, for lower versions you can use -notcontains

My first thought was to fall back to the .NET Framework and use LINQ. But it turns out that the PowerShell syntax is pretty ugly:

[Linq.Enumerable]::Except([object[]] $people1, [object[]] $people2)

(I'm not sure why the object[] casts are necessary, but without them PowerShell throws an "Cannot find an overload for "Except" and the argument count: "2"" exception.)

The idiomatic PowerShell would be:

$people1 | Where-Object { $people2 -notcontains $_ }

In addition to other good answers, following code depicts all SET operation on PowerShell Arrays:

#Union - Subtraction - Minus:
$a = (1,2,3,4)
$b = (1,2,77,88)
'UNION:'
Compare-Object $a $b -PassThru -IncludeEqual                    # union
''
'INTERSECTION:'
Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent  # intersection
''
'MINUS:'
'$a minus $b:'
$a | ?{$b -notcontains $_}                                      # a -minus b
'$b minus $a:'
$b | ?{$a -notcontains $_}                                      # b -minus a

HTH.

Related