2009-11-05 10 views
11

Mam 2 oddzielne listy i muszę porównać oba i uzyskać wszystko , ale na przecięciu tych dwóch list. Jak mogę to zrobić (C#)?Uzyskaj różnicę symetryczną od ogólnych list.

+0

co już wypróbowałeś? – fretje

+0

co masz na myśli przez wszystko, ale związek? –

+0

Wszystko oprócz związku jest zawsze niczym. Czy masz na myśli wszystko oprócz skrzyżowania? –

Odpowiedz

13

Możesz użyć numeru Except, aby uzyskać wszystkie, oprócz , skrzyżowanie obu list.

var differences = listA.Except(listB).Union(listB.Except(listA)); 

Jeśli chcesz dostać wszystko oprócz unii:

var allButUnion = new List<MyClass>(); 

(Związek jest wszystko w obu listach - wszystko ale Unia jest zbiorem pustym ...)

+1

Biorąc pod uwagę, że używasz słowa "przecięcie", aby opisać, co to znaczy po angielsku, czy to nie ma sensu używać go również w kodzie?:) –

+0

hehehe, prawda :) –

+0

Chociaż wydaje mi się, że pamiętam, kiedy musiałem to zrobić dla czegoś, to było trochę bardziej wydajne niż robienie total union i usuwanie skrzyżowania ... –

6

Czy masz na myśli wszystko, co tylko na jednej liście: lub inne? Jak o:

var allButIntersection = a.Union(b).Except(a.Intersect(b)); 

To może być nieco nieefektywne, ale to dość po prostu wskazuje, co masz na myśli (zakładając, że mam cię interpretowane poprawnie, oczywiście).

0

Korzystanie z wyjątkiem:

List<int> l1 = new List<int>(new[] { 1, 2, 3, 4 }); 
List<int> l2 = new List<int>(new[] { 2, 4 }); 
var l3 = l1.Except(l2); 
+1

Czy po prostu nie zwrócą rzeczy z l1, które nie są w l2? A co jeśli w L2 są przedmioty w l1? –

34

Jeśli masz na myśli zbiór wszystkiego, ale przecięcia (różnica symetryczna) można spróbować:

var set = new HashSet<Type>(list1); 
set.SymmetricExceptWith(list2); 
+2

Doskonały - to wygląda na najlepszy sposób robienia tego dla mnie. –

+2

Bardzo ładne! To znacznie czystsze niż to, co miałem. –

0
var theUnion = list1.Concat(list2); 
var theIntersection = list1.Intersect(list2); 
var theSymmetricDifference = theUnion.Except(theIntersection); 
1

coś takiego?

String[] one = new String[] { "Merry", "Metal", "Median", "Medium", "Malfunction", "Mean", "Measure", "Melt", "Merit", "Metaphysical", "Mental", "Menial", "Mend", "Find" }; 
      String[] two = new String[] { "Merry", "Metal", "Find", "Puncture", "Revise", "Clamp", "Menial" }; 

List<String> tmp = one.Except(two).ToList(); 
tmp.AddRange(two.Except(one)); 

String[] result = tmp.ToArray(); 
1

Oto ogólna metoda rozszerzenia. Kod Rosetty używa Concata, a Djeefther Souza mówi, że jest bardziej wydajny.

public static class LINQSetExtensions 
{ 
    // Made aware of the name for this from Swift 
    // https://stackoverflow.com/questions/1683147/get-the-symmetric-difference-from-generic-lists 
    // Generic implementation adapted from https://www.rosettacode.org/wiki/Symmetric_difference 
    public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> first, IEnumerable<T> second) 
    { 
     // I've used Union in the past, but I suppose Concat works. 
     // No idea if they perform differently. 
     return first.Except(second).Concat(second.Except(first)); 
    } 
} 

Nie testowałem tego. Myślę, że będzie to zależeć od tego, w jaki sposób wdrażane są Unia kontra konkluzje. W moim świecie snów .NET używa innego algorytmu, w zależności od typu danych lub ustalonego rozmiaru, choć dla IEnumerable nie może on wcześniej ustalić ustalonego rozmiaru.

Ponadto, możesz zignorować moją odpowiedź - Jon Skeet mówi, że metoda HashSet "Excellent - to wygląda na najlepszy sposób robienia tego dla mnie".

Powiązane problemy