2009-09-07 8 views
11

Tengo dos matrices de bytes en C# utilizando .NET 3.0.C# comparación de matriz de bytes

¿Cuál es la forma "más eficiente" de comparar si las dos matrices de bytes contienen el mismo contenido para cada elemento?

Por ejemplo, la matriz de bytes {0x1, 0x2} es la misma que {0x1, 0x2}. Pero el conjunto de bytes {0x1, 0x2} y el conjunto de bytes {0x2, 0x1} no son lo mismo.

+2

Duplicado de http://stackoverflow.com/questions/43289/ – Hafthor

Respuesta

32

Bueno, se podría utilizar:

public static bool ByteArraysEqual(byte[] b1, byte[] b2) 
{ 
    if (b1 == b2) return true; 
    if (b1 == null || b2 == null) return false; 
    if (b1.Length != b2.Length) return false; 
    for (int i=0; i < b1.Length; i++) 
    { 
     if (b1[i] != b2[i]) return false; 
    } 
    return true; 
} 

(normalmente utilizar llaves para todo, pero yo pensé que iba a experimentar con este estilo de diseño sólo para un cambio ...)

Esto tiene algunas optimizaciones que SequenceEqual no pueden (o no) realizar, como la verificación de longitud inicial. El acceso directo a la matriz también será un poco más eficiente que usar el enumerador.

La verdad es que es poco probable que haga una diferencia significativa en la mayoría de los casos ...

Se podría posiblemente hacerlo más rápido en código no administrado por lo que es comparar 32 o 64 bits a la vez en lugar de 8 - pero no quisiera codificar eso sobre la marcha.

+0

Me gusta su solución! – George2

+0

Hola Jon, ¿trabajas para stackoverflow? – Shiva

+2

@Shiva: No, yo trabajo para Google –

24

Puede utilizar el método SequenceEqual:

bool areEqual = firstArray.SequenceEqual(secondArray); 

Como se ha mencionado en los comentarios, SequenceEqual requiere .NET 3.5 (o LINQBridge si está usando VS2008 y la orientación de una versión anterior del marco).

+1

La forma más eficiente, creo. –

+1

No en términos de tiempo de ejecución, no lo es. –

+1

@Veton: ¡Sin duda es el que menos tipea! Vea la respuesta de Jon para algunas optimizaciones adicionales. – LukeH

3

Si usted quiere que sea muy rápido, puede utilizar código no seguro (que no siempre es posible):

public static bool ArraysEqual(byte[] b1, byte[] b2) 
    { 
     unsafe 
     { 
      if (b1.Length != b2.Length) 
       return false; 

      int n = b1.Length; 

      fixed (byte *p1 = b1, p2 = b2) 
      { 
       byte *ptr1 = p1; 
       byte *ptr2 = p2; 

       while (n-- > 0) 
       { 
        if (*ptr1++ != *ptr2++) 
         return false; 
       } 
      } 

      return true; 
     } 
    } 
5

Jon menciona la comparación de múltiples bytes a la vez utilizando código no seguro, así que tuve que dar una oportunidad:

public unsafe bool ByteArraysEqual(byte[] b1, byte[] b2) { 
    if (b1 == b2) return true; 
    if (b1 == null || b2 == null) return false; 
    if (b1.Length != b2.Length) return false; 
    int len = b1.Length; 
    fixed (byte* p1 = b1, p2 = b2) { 
     int* i1 = (int*)p1; 
     int* i2 = (int*)p2; 
     while (len >= 4) { 
     if (*i1 != *i2) return false; 
     i1++; 
     i2++; 
     len -= 4; 
     } 
     byte* c1 = (byte*)i1; 
     byte* c2 = (byte*)i2; 
     while (len > 0) { 
     if (*c1 != *c2) return false; 
     c1++; 
     c2++; 
     len--; 
     } 
    } 
    return true; 
} 

el código de seguridad se pone bastante optimizado (el compilador sabe que no tiene que comprobar los límites del índice, por ejemplo), por lo que no esperaría que el código no seguro para ser mucho más rápido. Cualquier diferencia significativa vendría de la capacidad de comparar varios bytes a la vez.

+0

Buen concepto, aunque el código no compila: "No se puede Asignar a 'p1' porque es una 'variable fija' " –

+0

@ Edward Brey: Tiene razón, eso no funcionará. Necesita declarar nuevos punteros dentro del bloque para poder cambiarlos. He corregido el código. – Guffa

+0

Es más rápido usar longs (8 bytes) en la compilación, incluso en máquinas de 32 bits. – Joe

2

Si no está demasiado preocupado por el rendimiento, puede considerar IStructuralEquatable.

.NET Framework Compatible con: 4.5, 4

igualdad estructural significa que dos objetos son iguales debido a que tienen valores iguales. Difiere de la igualdad de referencia.

Ejemplo:

static bool ByteArrayCompare(byte[] a1, byte[] a2) 
{ 
    IStructuralEquatable eqa1 = a1; 
    return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer); 
} 

REFERENCIA

  1. What problem does IStructuralEquatable and IStructuralComparable solve?
  2. Why aren't IStructuralEquatable and IStructuralComparable generic?
  3. IStructuralEquatable Interface
+1

Dando un punto a esta publicación: esta podría ser una manera de hacer las cosas cuando estamos usando las versiones recientes del marco. – timmi4sa

Cuestiones relacionadas