2012-03-07 17 views
40

Powiedzmy istniejąJak porównać dwie listy: <String>?

List<string> a1 = new List<string>(); 

List<string> a2 = new List<string>(); 

Czy istnieje sposób to zrobić w ten sposób?

if (a1 == a2) 
{ 

} 
+2

Czego dokładnie można się spodziewać? return true, jeśli obie listy mają te same wartości i w tej samej kolejności? –

Odpowiedz

87

Jeśli chcesz sprawdzić, czy elementy wewnątrz listy są równe i w tej samej kolejności, można użyć SequenceEqual:

if (a1.SequenceEqual(a2)) 

Zobacz pracuje w trybie online: ideone

+0

Yup! Chłodny! tyy !!!! –

+0

Nie zapominaj, że możesz również zaimplementować własny "IEqualityComparer" i podać go jako drugi argument (np. [A Porównywarka IgnoreCase dla łańcucha znaków] (http://msdn.microsoft.com/en-us/library/system.stringcomparer. currentcultureignorecase.aspx)). – Oliver

+0

@MarkByers, gdy próbuję SequenceEqual() w moim systemie, dlaczego jego rzuca wyjątek jak List nie zawiera definicji "SequenceEqual" i nie ma metody rozszerzenia "SequenceEqual" akceptując pierwszy argument typu .... .. –

6

Mogłabyś również użyj Except (daje ustawioną różnicę dwóch sekwencji), aby sprawdzić, czy istnieje różnica, czy nie:

IEnumerable<string> difference = a1.Except(a2); 
if(!difference.Any()){} 
+6

Dwa potencjalne problemy z używaniem 'Z wyjątkiem': Zwraca tylko pozycje 'a1', które nie istnieją w' a2' - więc jeśli 'a2' zawiera dodatkowe elementy, to zwróci fałszywy minus. Po drugie, nie uwzględnia duplikacji tego samego towaru, a jedynie istnienia. Wciąż potężne narzędzie, po prostu musi być używane ostrożnie. –

-3

można sprawdzić w każdym z poniższych sposobów, aby uzyskać listę

List<string> FilteredList = new List<string>(); 
//Comparing the two lists and gettings common elements. 
FilteredList = a1.Intersect(a2, StringComparer.OrdinalIgnoreCase); 
+0

Źle z twojej strony @DownVoters. Nie ma powodu do przegłosowania. Biorąc zemstę ??? –

+1

Nie głosowałem w dół - ale twoja odpowiedź w rzeczywistości nie odnosi się do pytania PO. Tworzy przecięcie, więc musisz zrobić dodatkowy krok, aby sprawdzić, czy to skrzyżowanie pasuje do "a1" i "a2". – RichK

+1

Ponadto, Intersect wyrzuci duplikaty, więc to tylko sprawdzi odrębne elementy w 'a1' i' a2'. – RichK

7

odkryłem że SequenceEqual nie jest najbardziej skutecznym sposobem, aby porównać dwie listy ciągów (początkowo z http://www.dotnetperls.com/sequenceequal).

chciałem przetestować ten sam więc stworzyłem dwie metody:. „Czytelność”

/// <summary> 
    /// Compares two string lists using LINQ's SequenceEqual. 
    /// </summary> 
    public bool CompareLists1(List<string> list1, List<string> list2) 
    { 
     return list1.SequenceEqual(list2); 
    } 

    /// <summary> 
    /// Compares two string lists using a loop. 
    /// </summary> 
    public bool CompareLists2(List<string> list1, List<string> list2) 
    { 
     if (list1.Count != list2.Count) 
      return false; 

     for (int i = 0; i < list1.Count; i++) 
     { 
      if (list1[i] != list2[i]) 
       return false; 
     } 

     return true; 
    } 

Druga metoda jest nieco kodu natknąłem i zastanawiał się, czy może to być refactored być (A także zastanawiał się, czy optymalizacja LINQ byłoby szybciej.)

Jak się okazuje, z dwoma listami zawierającymi 32K ciągi ponad 100 egzekucji:

  • metoda 1 zajęło średnio 6761.8 kleszczy
  • Method 2 miało średnią liczbę 3268.4 ticków

Zwykle preferuję LINQ dla zwięzłości, wydajności i czytelności kodu; ale w tym przypadku myślę, że preferowana jest metoda oparta na pętli.

Edit:

I zrekompilowane użyciu zoptymalizowanego kodu i prowadził badania na 1000 iteracji. Wyniki nadal faworyzują pętlę (nawet bardziej):

  • Metoda 1 trwało średnio 4227.2 kleszczy
  • metoda 2 trwało średnio 1831.9 kleszczy

testowane przy użyciu programu Visual Studio 2010, C# .NET 4 Profil klienta na rdzeniu i7-920

+0

To nie jest uczciwe porównanie z dwóch powodów: 1. Równa się nie stosuje, 2. Działa tylko dla list, co jest dobre dla tego pytania. – mycroes

0
private static bool CompareDictionaries(IDictionary<string, IEnumerable<string>> dict1, IDictionary<string, IEnumerable<string>> dict2) 
    { 
     if (dict1.Count != dict2.Count) 
     { 
      return false; 
     } 

     var keyDiff = dict1.Keys.Except(dict2.Keys); 
     if (keyDiff.Any()) 
     { 
      return false; 
     } 

     return (from key in dict1.Keys 
       let value1 = dict1[key] 
       let value2 = dict2[key] 
       select value1.Except(value2)).All(diffInValues => !diffInValues.Any()); 
    }