
$a = 1..5
$b = 4..8
$Yellow = $a | Where {$b -NotContains $_}
$Yellowenthält alle Elemente in $aaußer denen, die in enthalten sind $b:
PS C:\> $Yellow
1
2
3
$Blue = $b | Where {$a -NotContains $_}
$Blueenthält alle Elemente in $baußer denen, die in enthalten sind $a:
PS C:\> $Blue
6
7
8
$Green = $a | Where {$b -Contains $_}
Nicht in Frage, aber trotzdem; Greenenthält die Elemente, die in beiden $aund enthalten sind $b.
PS C:\> $Green
4
5
Hinweis : Whereist ein Alias von Where-Object. Alias kann mögliche Probleme verursachen und die Wartung von Skripten erschweren.
Nachtrag 12. Oktober 2019
Wie von @xtreampb und @ mklement0 kommentiert: Obwohl aus dem Beispiel in der Frage nicht ersichtlich, ist die Aufgabe, die die Frage impliziert (Werte "nicht gemeinsam"), die symmetrische Differenz zwischen den beiden Eingabesätzen (die Vereinigung von Gelb und Blau). .
Union
Der symmetrische Unterschied zwischen $aund $bkann wörtlich definiert werden als die Vereinigung von $Yellowund $Blue:
$NotGreen = $Yellow + $Blue
Welches ist ausgeschrieben:
$NotGreen = ($a | Where {$b -NotContains $_}) + ($b | Where {$a -NotContains $_})
Performance
Wie Sie vielleicht bemerken, gibt es in dieser Syntax einige (redundante) Schleifen: Alle Elemente in der Liste $adurchlaufen (verwenden Where) Elemente in der Liste $b(verwenden -NotConatins) und umgekehrt. Leider ist die Redundanz schwer zu vermeiden, da es schwierig ist, das Ergebnis jeder Seite vorherzusagen. Eine Hash-Tabelle ist normalerweise eine gute Lösung, um die Leistung redundanter Schleifen zu verbessern. Dazu definiere ich gerne die Frage neu: Holen Sie sich die Werte, die einmal in der Summe der Sammlungen erscheinen ( $a + $b) :
$Count = @{}
$a + $b | ForEach-Object {$Count[$_] += 1}
$Count.Keys | Where-Object {$Count[$_] -eq 1}
Wenn Sie die ForEachAnweisung anstelle des ForEach-ObjectCmdlets und die WhereMethode anstelle von verwenden, können Where-ObjectSie die Leistung um den Faktor 2,5 erhöhen:
$Count = @{}
ForEach ($Item in $a + $b) {$Count[$Item] += 1}
$Count.Keys.Where({$Count[$_] -eq 1})
LINQ
Aber Language Integrated Query (LINQ) leicht schlagen alle nativen Powershell und nativen .NET - Methoden (siehe auch High Performance Powershell mit LINQ und mklement0 Antwort für Can folgende Nested foreach - Schleife in Powershell vereinfacht werden? :
Um LINQ verwenden zu können, müssen Sie die Array-Typen explizit definieren:
[Int[]]$a = 1..5
[Int[]]$b = 4..8
Und benutze den [Linq.Enumerable]::Operator:
$Yellow = [Int[]][Linq.Enumerable]::Except($a, $b)
$Blue = [Int[]][Linq.Enumerable]::Except($b, $a)
$Green = [Int[]][Linq.Enumerable]::Intersect($a, $b)
$NotGreen = [Int[]]([Linq.Enumerable]::Except($a, $b) + [Linq.Enumerable]::Except($b, $a))
Benchmark
Die Benchmark-Ergebnisse hängen stark von der Größe der Sammlungen und der Anzahl der tatsächlich freigegebenen Elemente ab. Als "Durchschnitt" gehe ich davon aus, dass die Hälfte jeder Sammlung mit der anderen geteilt wird.
Using Time
Compare-Object 111,9712
NotContains 197,3792
ForEach-Object 82,8324
ForEach Statement 36,5721
LINQ 22,7091
Um einen guten Leistungsvergleich zu erhalten, sollten Caches gelöscht werden, indem beispielsweise eine neue PowerShell-Sitzung gestartet wird.
$a = 1..1000
$b = 500..1500
(Measure-Command {
Compare-Object -ReferenceObject $a -DifferenceObject $b -PassThru
}).TotalMilliseconds
(Measure-Command {
($a | Where {$b -NotContains $_}), ($b | Where {$a -NotContains $_})
}).TotalMilliseconds
(Measure-Command {
$Count = @{}
$a + $b | ForEach-Object {$Count[$_] += 1}
$Count.Keys | Where-Object {$Count[$_] -eq 1}
}).TotalMilliseconds
(Measure-Command {
$Count = @{}
ForEach ($Item in $a + $b) {$Count[$Item] += 1}
$Count.Keys.Where({$Count[$_] -eq 1})
}).TotalMilliseconds
[Int[]]$a = $a
[Int[]]$b = $b
(Measure-Command {
[Int[]]([Linq.Enumerable]::Except($a, $b) + [Linq.Enumerable]::Except($b, $a))
}).TotalMilliseconds
Compare-ObjectAntworten hier implementieren: Der symmetrische Unterschied zwischen zwei Mengen wird bestimmt - aber nur, wenn die Eingabearrays wirklich Mengen sind (wie in der Frage), dh nein doppelte Elemente .