2010-09-21 10 views
6

Wiem, że LINQ ma metodę SequenceEquals. Ta metoda zapewnia, że ​​każda wartość elementu w każdym kolekcji jest zgodna w tej samej kolejności.Czy istnieje metoda równoważna LINQ?

To, czego szukam, to bardziej "równoważny" typ funkcji. Tylko, że obie sekwencje zawierają te same elementy, niekoniecznie w tej samej kolejności.

Na przykład nUnit ma CollectionAssert.AreEqual() i CollectionAssert.AreEquivalent(), które robią to, co wyjaśniam.

wiem, że mogę to zrobić poprzez:

  1. zamawiania list z wyprzedzeniem i przy użyciu SequenceEquals
  2. Korzystanie Intersect, a następnie zobaczyć, czy przecięcie jest równe oryginalnej kolejności.

Przykład:

var source = new[] {5, 6, 7}; 
source.Intersect(new[] {5, 7, 6}).Count() == source.Length; 
+1

Jest pomyłka w przykładzie odpowiedź. Musisz porównać to z obydwoma liczbami, w przeciwnym razie twoja funkcja zwróci wartość "prawda", gdy źródło jest podzbiorem celu. To znaczy. źródło {5,6} i cel {5,7,6} – cellik

Odpowiedz

8

Chciałbym utworzyć metodę rozszerzenia, która przecina, a następnie porównuje liczby.

+0

Otrzymujesz odpowiedź dając mi pomysł, aby porównać liczby, dzięki czemu sprawiło, że było ładnie i kompaktowo, dzięki! Wygląda to tak: var source = new [] {5, 6, 7}; source.Intersect (new [] {5, 7, 6}). Count() == source.Length; – CubanX

+0

@CubanX: Zauważ, że jeśli źródło zawiera jakiekolwiek duplikaty, to nawet 'source.SetEquals (source)' zwróci false. –

+0

@Jon Dobra sprawa, może będę musiała rzucić tam wyraźne, aby się nie stało. – CubanX

9

można zbudować zestaw, a następnie użyć HashSet<T>.SetEquals. Nie jest to ściśle w LINQ, ale ładnie z nim gra :)

Oczywiście, można łatwo napisać własną metodę rozszerzenia, aby przedłużyć tę. Coś takiego:

public static bool SetEquals<T>(this IEnumerable<T> source, IEnumerable<T> other) 
{ 
    HashSet<T> hashSet = new HashSet<T>(source); 
    return hashSet.SetEquals(other); // Doesn't recurse! Calls HashSet.SetEquals 
} 

EDIT: Jak zauważył w komentarzach, to ignoruje, ile razy występują elementy, jak również kolejność - tak { 1, 2 } byłoby „równy” do { 1, 2, 1, 2, 1, 1, 1 }. Jeśli nie tego chcesz, to będzie trochę bardziej skomplikowane.

+0

więc 1,2 byłby "równy" 1,1,1,2,2,2? – spender

+0

@spender: Dla * ustaw * równości, to prawda. Zestaw elementów w każdej kolekcji jest taki sam. Warto jednak podkreślić - będzie edytować. –

+0

Jon, czasami w takich metodach, nie mogę zdecydować, czy napisać tak, jak go masz, czy też zrobić coś w stylu 'HashSet hashSet = source as HashSet ?? nowy HashSet (źródło); '* potencjalnie * oszczędność kosztów budowy nowego' HashSet '. Czy masz na to zdanie? –

2

zrobiłem to w ten sposób:

public static bool SetEquivalent<T>(
    this IEnumerable<T> aSet, 
    IEnumerable<T> anotherSet) 
{ 
    var diffA = aSet.Except(anotherSet).Count(); 
    var diffB = anotherSet.Except(aSet).Count(); 
    return diffA == diffB && diffA == 0; 
} 
Powiązane problemy