2010-07-12 31 views
107

In Java, Arrays.equals() consente di confrontare facilmente il contenuto di due array di base (i sovraccarichi sono disponibili per tutti i tipi di base).Il modo più semplice per confrontare gli array in C#

Esiste una cosa del genere in C#? Esiste un modo "magico" per confrontare il contenuto di due array in C#?

+0

Aggiunto '.net' ai tag perché questa tecnica potrebbe essere noi ed in altre lingue basate su .net simili. –

+1

Per chiunque stia leggendo questo, tenere presente che la risposta accettata sta usando SequenceEqual. SequenceEqual non solo controlla se contengono gli stessi dati, ma anche se contengono gli stessi dati nello stesso ordine –

risposta

163

È possibile utilizzare SequenceEqual. Questo funziona per qualsiasi IEnumerable<T>, non solo per gli array.

+1

Nota per OP: SequenceEqual non fa parte di C#, fa parte di .NET. –

+8

@John, C# è parte di .NET. Quindi, per transitività, 'SequenceEqual' è parte di C#. ;) –

+0

e C# fa sempre parte di .NET no? – kenny

41

Utilizzare SequenceEqual in LINQ.

int[] arr1 = new int[] { 1,2,3}; 
int[] arr2 = new int[] { 3,2,1 }; 

Console.WriteLine(arr1.SequenceEqual(arr2)); // false 
Console.WriteLine(arr1.Reverse().SequenceEqual(arr2)); // true 
+0

Tenete a mente che questo getta per argomenti nulli, quindi assicuratevi di non supporre che 'new int [] {1}.SequenceEquals (null) == false' – kai

22

anche per gli array (e tuple) è possibile utilizzare nuove interfacce da NET 4.0: IStructuralComparable e IStructuralEquatable. Usandoli puoi non solo controllare l'uguaglianza degli array ma anche confrontarli.

static class StructuralExtensions 
{ 
    public static bool StructuralEquals<T>(this T a, T b) 
     where T : IStructuralEquatable 
    { 
     return a.Equals(b, StructuralComparisons.StructuralEqualityComparer); 
    } 

    public static int StructuralCompare<T>(this T a, T b) 
     where T : IStructuralComparable 
    { 
     return a.CompareTo(b, StructuralComparisons.StructuralComparer); 
    } 
} 

{ 
    var a = new[] { 1, 2, 3 }; 
    var b = new[] { 1, 2, 3 }; 
    Console.WriteLine(a.Equals(b)); // False 
    Console.WriteLine(a.StructuralEquals(b)); // True 
} 
{ 
    var a = new[] { 1, 3, 3 }; 
    var b = new[] { 1, 2, 3 }; 
    Console.WriteLine(a.StructuralCompare(b)); // 1 
} 
+0

Perdonami, dovrebbe essere un 1 o uno 0 in 'a.StructuralCompare (b)'? – mafu

0

Ecco una strana implementazione.

static bool ArraysEqual<T>(T[] a, T[] b) 
    { 
     int k = 0; 
     return a.All(x => x.Equals(b[k++])); 
    } 
+2

Se 'b' inizia con tutti gli stessi elementi di' a', ma poi ha alcuni elementi aggiuntivi, questo metodo restituirebbe erroneamente 'true'. Se 'a' è più lungo di' b' si genera un'eccezione. –

14

Per NET 4.0 e più alto è possibile confrontare gli elementi in array o tuple via utilizzando StructuralComparisons Tipo:

object[] a1 = { "string", 123, true }; 
object[] a2 = { "string", 123, true }; 

Console.WriteLine (a1 == a2);  // False (because arrays is reference types) 
Console.WriteLine (a1.Equals (a2)); // False (because arrays is reference types) 

IStructuralEquatable se1 = a1; 
//Next returns True 
Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer)); 
+0

Modifica: parlato troppo presto. Posso eseguire StructualEqualityCompare con IStructuralComparable? Voglio chiamare CompareTo con due matrici di oggetti per scoprire quale viene "prima". Ho provato IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, StructuralComparisons.StructuralEqualityComparer)); Ottenere: impossibile convertire da 'System.Collections.IEqualityComparer' a 'System.Collections.IComparer' – shindigo

+1

OK: la chiamata corretta è: IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, StructuralComparisons.StructuralComparer)); – shindigo

10

SequenceEqual tornerà vero solo se due condizioni o incontrato.

  1. Contengono gli stessi elementi.
  2. Gli elementi sono nello stesso ordine.

Se solo si desidera controllare se contengono gli stessi elementi indipendentemente dal loro ordine e il problema è del tipo

Does values2 contenere tutti i valori contenuti nella values1?

è possibile utilizzare LINQ metodo di estensione Enumerable.Except e quindi verificare se il risultato ha un valore. Ecco un esempio

int[] values1 = { 1, 2, 3, 4 }; 
int[] values2 = { 1, 2, 5 }; 
var result = values1.Except(values2); 
if(result.Count()==0) 
{ 
    //They are the same 
} 
else 
{ 
    //They are different 
} 

E anche utilizzando questo si ottiene automaticamente gli elementi diversi. Due piccioni con una fava.

tenere a mente, se si esegue il codice come questo

var result = values2.Except(values1); 

si ottengono risultati diversi.

Nel mio caso, ho una copia locale di un array e voglio controllare se qualcosa è stato rimosso dall'array originale, quindi utilizzo questo metodo.

1

elementwise confrontare? che dire di

public void Linq78a() 
{ 
int[] numbers1 = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; 
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; 
bool bb = numbers.Zip(numbers1, (a, b) => (a == b)).Any(p => !p); 
if (!bb) Console.WriteLine("Lists are equal (bb)"); 
    else Console.WriteLine("Lists are not equal (bb)"); 
} 

Sostituisci la condizione (a == b) con qualsiasi cosa desideri confrontare in a eb.

(questo combina due esempi da MSDN developer Linq samples)

0

Ho fatto questo in studi visivi e ha funzionato perfettamente; confrontare gli array indice per indice con questo codice breve.

private void compareButton_Click(object sender, EventArgs e) 
     { 
      int[] answer = { 1, 3, 4, 6, 8, 9, 5, 4, 0, 6 }; 
      int[] exam = { 1, 2, 3, 6, 8, 9, 5, 4, 0, 7 }; 

      int correctAnswers = 0; 
      int wrongAnswers = 0; 

      for (int index = 0; index < answer.Length; index++) 
      { 
       if (answer[index] == exam[index]) 
       { 
        correctAnswers += 1; 
       } 
       else 
       { 
        wrongAnswers += 1; 
       } 
      } 

      outputLabel.Text = ("The matching numbers are " + correctAnswers + 
       "\n" + "The non matching numbers are " + wrongAnswers); 
     } 

l'uscita sarà; I numeri corrispondenti sono 7 I numeri non corrispondenti sono 3

4

per i test unitari, è possibile utilizzare al posto di CollectionAssert.AreEqualAssert.AreEqual.

È probabilmente il modo più semplice.

0

Se si desidera gestire null ingressi con grazia, e ignorare l'ordine degli elementi, provare la seguente soluzione:

static class Extensions 
{ 
    public static bool ItemsEqual<TSource>(this TSource[] array1, TSource[] array2) 
    { 
     if (array1 == null && array2 == null) 
      return true; 
     if (array1 == null || array2 == null) 
      return false; 
     return array1.Count() == array2.Count() && !array1.Except(array2).Any(); 
    } 
} 

Il codice di test si presenta come:

class Program 
{ 
    static void Main(string[] args) 
    { 
     int[] a1 = new int[] { 1, 2, 3 }; 
     int[] a2 = new int[] { 3, 2, 1 }; 
     int[] a3 = new int[] { 1, 3 }; 
     int[] a4 = null; 
     int[] a5 = null; 
     int[] a6 = new int[0]; 

     Console.WriteLine(a1.ItemsEqual(a2)); // Output: True. 
     Console.WriteLine(a2.ItemsEqual(a3)); // Output: False. 
     Console.WriteLine(a4.ItemsEqual(a5)); // Output: True. No Exception. 
     Console.WriteLine(a4.ItemsEqual(a3)); // Output: False. No Exception. 
     Console.WriteLine(a5.ItemsEqual(a6)); // Output: False. No Exception. 
    } 
} 
1

Per alcune applicazioni può be better:

string.Join("", arr1) == string.Join("", arr2) 
Problemi correlati