edwin
edwin

Reputation: 243

Array subtraction in PowerShell

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?

Upvotes: 6

Views: 10143

Answers (4)

Eddie Kumar
Eddie Kumar

Reputation: 1488

Additionally following code mimics different SET operations (Union, Subtraction & Minus) that can be used with PowerShell Arrays:

#assume variables $a and $b contain two sets of integer arrays:
$a = (1,2,3,4)
$b = (1,2,77,88)

'UNION: - merges both the outputs + removes the duplicate values'
Compare-Object $a $b -PassThru -IncludeEqual                    # union
#"Output: 1,2,77,88,3,4"

'INTERSECTION: - returns only common values'
Compare-Object $a $b -PassThru -IncludeEqual -ExcludeDifferent  # intersection
#"Output: 1,2"

'MINUS: - returns only exclusions'
'$a minus $b:'
$a | ?{$b -notcontains $_}                                      # a -minus b
#"Output: 3,4"

'$b minus $a:'
$b | ?{$a -notcontains $_}                                      # b -minus a
#"Output: 77,88"

HTH.

Upvotes: 0

Avshalom
Avshalom

Reputation: 8889

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

Upvotes: 11

Joe White
Joe White

Reputation: 97778

The idiomatic PowerShell would be:

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

Upvotes: 0

Joe White
Joe White

Reputation: 97778

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.)

Upvotes: 2

Related Questions