2011-02-01 55 views
5

¿Cuál es la forma más sencilla de encontrar un byte [] dentro de otro byte []? Tengo la sensación de que podría hacerlo con Linq pero no sé cómo.¿Encontrar una matriz (byte []) dentro de otra matriz?

Nota: Hice una búsqueda con el [c#] y no encontré nada, estoy sorprendido.

+0

Creo que necesitamos más información. ¿Estás tratando de encontrar una subsecuencia de bytes dentro de una matriz de bytes? ¿Podría dar un ejemplo? – Andrew

+2

Véase, por ejemplo, el [algoritmo Knuth-Morris-Pratt] (http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm). – jason

Respuesta

7

Aquí está una manera (ingenuo?) Sencilla de hacerlo:

static int search(byte[] haystack, byte[] needle) 
{ 
    for (int i = 0; i <= haystack.Length - needle.Length; i++) 
    { 
     if (match(haystack, needle, i)) 
     { 
      return i; 
     } 
    } 
    return -1; 
} 

static bool match(byte[] haystack, byte[] needle, int start) 
{ 
    if (needle.Length + start > haystack.Length) 
    { 
     return false; 
    } 
    else 
    { 
     for (int i = 0; i < needle.Length; i++) 
     { 
      if (needle[i] != haystack[i + start]) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
} 
+0

Perfecto, tal como lo necesitaba. Para mal no puedo hacer esto con linq o algo incorporado. ¿Escribiste esto ahora? o copiar/pegar desde algún lugar? –

+0

Tenga en cuenta que, dependiendo de la entrada, esto es potencialmente muy lento. – jason

+0

@acidzombie - Simplemente lo escribí. @Jason - sí puede ser lento, pero simple. – Ergwun

-2

usted probablemente podría haber pensado esto usted mismo, pero a veces me gusta hacer lo simple.

bool found = false; 
int i = 0; 
for(; i < byteArray.Length || found; i++) 
{ 
    if(byteArray[i] == lookingFor) 
    { 
    found = true; 
    } 
} 
+2

Creo que malinterpretaste la pregunta. Piense en la pregunta como encontrar una palabra en una cadena, pero la palabra es un 'byte []' y la cadena es otro 'byte []'. – jason

+0

Sí, lo leí como byte en una matriz de bytes. mi error. si tiene ascii, podría usar ASCIIEncoding.ASCII.GetString para hacer una cadena de su byte [] –

0

Trate de éste con el uso de las expresiones lambda:

private bool CheckPatternInArray(byte[] array, byte[] pattern) 
{ 
    int fidx = 0; 
    int result = Array.FindIndex(array, 0, array.Length, (byte b) => 
      { 
       fidx = (b == pattern[fidx]) ? fidx + 1 : 0; 
       return (fidx == pattern.Length); 
      }); 
    return (result >= pattern.Length - 1); 
} 

Si usted está después de la rápida, cheque soluciones here.

18

Aquí es una versión más rápida de Ergwun's excellent answer:

static int SearchBytes(byte[] haystack, byte[] needle) { 
    var len = needle.Length; 
    var limit = haystack.Length - len; 
    for(var i = 0; i <= limit; i++) { 
     var k = 0; 
     for(; k < len; k++) { 
      if(needle[k] != haystack[i+k]) break; 
     } 
     if(k == len) return i; 
    } 
    return -1; 
} 

En un breve ensayo con un pajar de 11 MB y la aguja 9 bytes, esto fue alrededor de tres veces más rápido.

Las optimizaciones son:

  • Sin función llamada cada vez a través del bucle exterior.
  • La longitud de la aguja y el límite de búsqueda se guardan en caché.
  • Se quitó la prueba de longitud redundante al comienzo de match().

Por supuesto, para arreglos de byte largo desearía utilizar algo así como una búsqueda de Boyer-Moore, pero para muchos fines un algoritmo simple como este es suficiente, y tiene la virtud de ser corto y fácil de entender y verificar

Cuestiones relacionadas