2010-05-26 13 views
20

Mam dwie tablice jakPorównywanie tablic używając LINQ w C#

string[] a = { "a", "b", "c" }; 
string[] b = { "a", "b", "c" }; 

muszę porównać dwie tablice przy użyciu LINQ.

Porównanie powinno mieć miejsce tylko wtedy, gdy obie macierze mają ten sam rozmiar. Dane mogą być w dowolnej kolejności i nadal zwracają wartość true, jeśli wszystkie wartości a [] i wszystkie wartości b [] są takie same.

+0

od X w od rw b gdzie x == y zaznaczyć x == y ale jej nie można poprawić ... nie przechowywać w zmiennej Boolean –

+0

Czy każda tablica ma unikatowe wartości? Kiedy uważasz, że dwie tablice są takie same? czy mają te same elementy? te same elementy w tej samej kolejności? –

+0

Czy szukasz pojedynczej odpowiedzi bool, jeśli obie są idealnie takie same lub szukasz sprawdzić, czy każdy element jest taki sam jak jego partnera. –

Odpowiedz

27
string[] a = { "a", "b" }; 
string[] b = { "a", "b" }; 

return (a.Length == b.Length && a.Intersect(b).Count() == a.Length); 

Po pewnym testowania wydajności:

  • Ponad 10.000 małe struny - 5ms
  • Ponad 100.000 małe Strings - 99ms
  • Ponad milion małych Strings - Śr. 601ms
  • Ponad 100.000 ~ 500 ciągi znaków - 190ms
+1

, ale nie sądzę, że wydajność jest w porządku. Skrzyżowanie nie jest tanią operacją. – Andrey

+0

@Andrey - zależy to również od wielkości listy. –

+4

Syntaktycznie, powiedziałbym 'return (a.Length == b.Length &&.Intersect (b) .Count() == a.Length)', ale to tylko ja. – ZombieSheep

19

Nie jestem pewien co do wydajności, ale to wydaje się działać.

string[] a = { "a", "b", "c" }; 
string[] b = { "a", "b", "c" }; 

bool result = a.SequenceEqual(b); 
Assert.AreEqual(true, result); 

Jednak nie jest niezależny od zamówienia, więc nie spełnia wymagań PO.

string[] a = { "a", "b", "c" }; 
string[] b = { "a", "c", "b" }; 

bool result = a.SequenceEqual(b); 
Assert.AreEqual(false, result); 
+2

Co masz na myśli mówiąc "to jest niezależny porządek"? SequenceEqual NIE jest niezależnym zamówieniem. W twoim drugim przykładzie kodu zwróci false –

+0

Masz rację. Edytowane. –

+0

Nie powodując zignorowania, ale to nie odpowiada na pytanie. Jak na operację: 'nie w tej samej kolejności ... ale dwie tablice powinny mieć równą wielkość ' –

4

jeśli kolejność nie ma znaczenia czy mogą istnieć duplikaty, to może:

public static class IEnumerableExtensions 
{ 
    public static bool HasSameContentsAs<T>(this ICollection<T> source, 
              ICollection<T> other) 
    { 
     if (source.Count != other.Count) 
     { 
      return false; 
     } 
     var s = source 
      .GroupBy(x => x) 
      .ToDictionary(x => x.Key, x => x.Count()); 
     var o = other 
      .GroupBy(x => x) 
      .ToDictionary(x => x.Key, x => x.Count()); 
     int count; 
     return s.Count == o.Count && 
       s.All(x => o.TryGetValue(x.Key, out count) && 
          count == x.Value); 
    } 
} 

wykorzystania:

string[] a = { "a", "b", "c" }; 
string[] b = { "c", "a", "b" }; 

bool containSame = a.HasSameContentsAs(b); 

niektórych przypadkach zastosowanie:

  • inna długości (spodziewać się fałszywych)

    string[] a = { "a", "b", "c" }; 
    string[] b = { "b", "c" }; 
    
  • inny porządek (oczekiwać prawdziwe)

    string[] a = { "a", "b", "c" }; 
    string[] b = { "b", "c", "a" }; 
    

działa również wtedy, gdy wejścia mogą zawierać duplikatów, choć nie jest jasne, z pytaniem, czy to cecha jest pożądana, czy nie Rozważmy:

  • zduplikowane elementy mają taką samą liczbę (oczekiwać true)

    string[] a = { "a", "b", "b", "c" }; 
    string[] b = { "a", "b", "c", "b" }; 
    
  • zduplikowane elementy o różnej morfologii (oczekiwać false)

    string[] a = { "a", "b", "b", "b", "c" }; 
    string[] b = { "a", "b", "c", "b", "c" }; 
    
+0

Jeśli porównasz ich rozmiary, najpierw musisz obojgtać całą operację? –

+1

@Scott, Tak. Rozważmy a = {"a", "b", "c"}; b = {"c", "a". "a"}; tej samej długości, ale unikatowe elementy w b są podzbiorem tych w – Handcraftsman

5

Myślę, że to zawsze będzie O (n log n) operacji, tak bym właśnie rodzaj obu tablicach i porównaj je np używając SequenceEqual.

3
IDictionary<int, object> a = new Dictionary<int, object>(); 
IDictionary<int, object> b = new Dictionary<int, object>(); 
a.Add(1, "1"); 
a.Add(2, 2); 
a.Add(3, "3"); 

b.Add(3, "3"); 
b.Add(1, "1"); 
b.Add(2, 2); 

Console.WriteLine(a.All(i => b.Contains(i)) && b.All(i => a.Contains(i))); 
2

To działa prawidłowo z duplikatów i sprawdzić każdy element

a.Length == b.Length && !a.Where((t, i) => t != b[i]).Any() 
Powiązane problemy