2010-07-12 26 views
107

En Java, Arrays.equals() permite comparar fácilmente el contenido de dos matrices básicas (las sobrecargas están disponibles para todos los tipos básicos).La forma más fácil de comparar matrices en C#

¿Existe tal cosa en C#? ¿Hay alguna forma "mágica" de comparar el contenido de dos matrices en C#?

+0

Agregué '.net' a las etiquetas porque esta técnica podría ser nosotros ed en otros lenguajes similares basados ​​en .net. –

+1

Para cualquiera que lea esto, tenga en cuenta que la respuesta aceptada es el uso de SequenceEqual. SequenceEqual no solo comprueba si contienen los mismos datos, sino también si contienen los mismos datos en el mismo orden –

Respuesta

163

Puede usar SequenceEqual. Esto funciona para cualquier IEnumerable<T>, no solo para matrices.

+1

Nota para OP: SequenceEqual no es parte de C#, es parte de .NET. –

+8

@John, C# es parte de .NET. Entonces, por transitividad, 'SequenceEqual' es parte de C#. ;) –

+0

y C# siempre es parte de .NET no? – kenny

41

Use SequenceEqual en 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

Tenga en cuenta que esto arroja argumentos nulos, así que asegúrese de no asumir que 'new int [] {1}.SequenceEquals (null) == false' – kai

22

también para las matrices (y tuplas) que puede utilizar nuevas interfaces de .NET 4.0: IStructuralComparable y IStructuralEquatable. Utilizándolos no solo puedes verificar la igualdad de matrices sino también compararlas.

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

Disculpe, ¿debería ser un 1 o un 0 en 'a.StructuralCompare (b)'? – mafu

0

Aquí hay una implementación extraña.

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

Si 'b' comienza con todos los mismos elementos como' a', pero luego tiene algunos elementos adicionales, este método incorrectamente devolverá 'true'. Si 'a' es más largo que' b' esto arrojaría una excepción. –

14

Para .NET 4.0 y más alto se puede comparar elementos en serie o tuplas mediante el uso de 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

Editar: Habló demasiado pronto. ¿Puedo hacer el StructualEqualityCompare con IStructuralComparable? Quiero llamar a CompareTo con dos matrices de objetos para descubrir cuál viene "primero". Intenté IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, StructuralComparisons.StructuralEqualityComparer)); Obteniendo: no se puede convertir de 'System.Collections.IEqualityComparer' a 'System.Collections.IComparer' – shindigo

+1

OK - la llamada correcta es: IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, StructuralComparisons.StructuralComparer)); – shindigo

10

SequenceEqual sólo devolverá verdadero si dos condiciones o conocido.

  1. Contienen los mismos elementos.
  2. Los elementos están en el mismo orden.

Si sólo desea comprobar si contienen los mismos elementos, independientemente de su orden y su problema es del tipo

¿El values2 contener todos los valores contenidos en valores1?

puede utilizar el método de extensión LINQ Enumerable.Except y luego comprobar si el resultado tiene algún valor. Aquí hay un ejemplo

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 
} 

Y también al usar esto, usted obtiene los diferentes artículos también automáticamente. Dos pájaros con una piedra.

tener en cuenta, si se ejecuta el código como este

var result = values2.Except(values1); 

obtendrá resultados diferentes.

En mi caso, tengo una copia local de una matriz y quiero comprobar si se ha eliminado algo de la matriz original, así que utilizo este método.

1

elementwise comparar? ¿qué pasa con

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)"); 
} 

Reemplace la condición (a == b) por cualquier cosa que desee comparar en ay b.

(esto se combina dos ejemplos de MSDN developer Linq samples)

0

hice esto en estudios visuales y funcionó perfectamente; comparando matrices índice por índice con short este código.

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); 
     } 

la salida será; Los números coincidentes son 7 Los números que no coinciden son 3

4

Para las pruebas unitarias, puede usar CollectionAssert.AreEqual en lugar de Assert.AreEqual.

Probablemente sea la forma más fácil.

0

Si desea manejar null entradas de gracia, e ignorar el orden de los elementos, pruebe la solución siguiente:

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(); 
    } 
} 

El código de prueba se parece a:

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

Para algunas aplicaciones puede ser mejor:

string.Join("", arr1) == string.Join("", arr2) 
Cuestiones relacionadas