2014-06-23 11 views
6

Ho due liste come sotto, come posso dire che hanno gli stessi elementi. L'ordine non è importante.Controlla se due liste hanno gli stessi articoli

var list1 = new List<int> {1,2,3}; 
var list2 = new List<int> {2,1,3}; 

Come posso dire che questi sono uguali? Devo scrivere il mio metodo o esiste un metodo integrato per questo?

+1

Non credo che ci sia qualcosa di costruito in ... buon candidato per un metodo di estensione – Liath

risposta

14

Ecco a cosa servono i set (ad es. HashSet<T>). Gli insiemi non hanno un ordine definito e SetEquals verifica se il set e un'altra raccolta contengono gli stessi elementi.

var set = new HashSet<int>(list1) 
var equals = set.SetEquals(list2); 
+0

Sarebbe questo lavoro se ho un elenco di oggetti, invece di numeri interi? – Vahid

+0

@Vahid Sì, lo farebbe. – dcastro

+1

@Vahid: dipende da se l'oggetto sovrascrive 'Equals' (+' GetHashCode'). Puoi anche passare un custom 'IEqualityComparer ' al costruttore di 'HashSet' Leggi: http://stackoverflow.com/questions/8952003/how-does-hashset-compare-elements-for-equality –

0

Che dire:

list1.Count == lis2.Count, then list1.Except(list2).Any() 

o forse (ma probabilmente non):

list1.Intersect(list2).Count == list1.Count; 

Edit: Rotem è corretto. Ho letto male la domanda. Questo funzionerà.

+3

Penso che tu intenda "Eccetto". 'Instersect' restituirebbe tutti gli elementi se fossero uguali, richiedendo di controllare' list1.Intersect (list2) .Count() == list1.Count; ' – Rotem

+0

Questo errore si verifica quando' list1' è un sottoinsieme di 'list2'. –

1

Si può provare Except

var result = list1.Except(list2).ToList(); 

Except restituisce quegli elementi in primo che non appaiono in seconda

+0

Perché 'stringa'? Inoltre, dov'è il controllo per l'uguaglianza? – Rotem

+0

Se 'list1' è vuoto, restituisce una lista vuota che non significa che entrambi sono uguali. Fallisce anche se list1 è un sottoinsieme di list2. A parte questo, non è necessario creare un'altra raccolta solo per verificare se entrambe le liste sono uguali. –

7

È possibile utilizzare !Except + Any:

bool list1InList2 = !list1.Except(list2).Any(); 

Questo non controlla se entrambi avere gli stessi elementi ma se list1 è contenuto in list2 (ignorando i duplicati).

Se vuoi sapere se list2 è contenuto in list1, utilizzare:

bool list2InList1 = !list2.Except(list1).Any(); 

così si doveva fare entrambe le controlla se ci si vuole assicurare che entrambe le liste contengono gli stessi elementi.

Se si desidera tenere conto del fatto che entrambi gli elenchi hanno le stesse dimensioni, verificare con list1.Count==list2.Count. Ma questo controllo non è utile se si utilizza un metodo impostato (vedere Harald's comment), non ha molto senso confrontare i conteggi se si ignorano i duplicati in seguito.

In generale HashSet<T> ha alcuni metodi efficaci per verificare se due sequenze hanno gli stessi elementi (ignorando i duplicati), dcastro already showed.


Se si desidera una soluzione efficiente per determinare se due liste contengono gli stessi elementi, stesso conteggio e duplicati non ignorando ma ignorando l'ordine (altrimenti utilizzare SequenceEquals):

public static bool SequenceEqualsIgnoreOrder<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer = null) 
{ 
    if(list1 is ICollection<T> ilist1 && list2 is ICollection<T> ilist2 && ilist1.Count != ilist2.Count) 
     return false; 

    if (comparer == null) 
     comparer = EqualityComparer<T>.Default; 

    var itemCounts = new Dictionary<T, int>(comparer); 
    foreach (T s in list1) 
    { 
     if (itemCounts.ContainsKey(s)) 
     { 
      itemCounts[s]++; 
     } 
     else 
     { 
      itemCounts.Add(s, 1); 
     } 
    } 
    foreach (T s in list2) 
    { 
     if (itemCounts.ContainsKey(s)) 
     { 
      itemCounts[s]--; 
     } 
     else 
     { 
      return false; 
     } 
    } 
    return itemCounts.Values.All(c => c == 0); 
} 

Uso:

var list1 = new List<int> { 1, 2, 3, 1 }; 
var list2 = new List<int> { 2, 1, 3, 2 }; 
bool sameItemsIgnoringOrder = list1.SequenceEqualsIgnoreOrder(list2); 
// false because same count and same items but 1 appaears twice in list1 but once in list2 

Se le questioni di ordine ed i duplicati contano troppo, uso:

bool sameItemsSameOrder = list1.SequenceEqual(list2); 
+2

+1 metodo migliore. – Rotem

+0

@Rotem Mi chiedo se questo è più veloce del metodo suggerito da 'dcastro'? – Vahid

+0

Grazie a Tim, vuoi dire che il metodo di 'dcastro' ignorerà i duplicati? – Vahid

0

Senza l'utilizzo di LINQ.

private static bool AreListsEqual(List<int> list1, List<int> list2) 
{ 
     var areListsEqual = true; 

     if (list1.Count != list2.Count) 
      return false; 

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

     return areListsEqual; 
} 
+1

L'ordine non è importante ma la soluzione restituisce false quando i numeri non sono nello stesso ordine. – Vahid

Problemi correlati