una recorrer multidimensionales multidimensional matriz matrices matrice imprimir dinamico dibujar declarar como bidimensional arreglos arreglo array 5x5 php arrays multidimensional-array hash md5

recorrer - matriz 5x5 php



¿La mejor forma de PHP para la matriz multidimensional MD5? (12)

Aparte de la excelente respuesta de Brock (+1), cualquier biblioteca hash decente le permite actualizar el hash en incrementos, por lo que debería poder actualizarse con cada cadena secuencialmente, en lugar de tener que crear una cadena gigante.

Ver: hash_update

¿Cuál es la mejor manera de generar un MD5 (o cualquier otro hash) de una matriz multidimensional?

Podría escribir fácilmente un bucle que atravesaría cada nivel de la matriz, concatenando cada valor en una cadena y simplemente ejecutando el MD5 en la cadena.

Sin embargo, esto parece engorroso en el mejor de los casos y me pregunté si habría una función funky que tomaría una matriz multidimensional y la picaría.


Creo que este podría ser un buen consejo:

Class hasharray { public function array_flat($in,$keys=array(),$out=array()){ foreach($in as $k => $v){ $keys[] = $k; if(is_array($v)){ $out = $this->array_flat($v,$keys,$out); }else{ $out[implode("/",$keys)] = $v; } array_pop($keys); } return $out; } public function array_hash($in){ $a = $this->array_flat($in); ksort($a); return md5(json_encode($a)); } } $h = new hasharray; echo $h->array_hash($multi_dimensional_array);


La respuesta depende en gran medida de los tipos de datos de los valores de matriz. Para grandes cadenas de uso:

md5(serialize($array));

Para cadenas cortas y enteros use:

md5(json_encode($array));

4 funciones integradas de PHP pueden transformar una matriz en una cadena: serialize() , json_encode() , var_export() , print_r() .

Aviso: la función json_encode() ralentiza al procesar matrices asociativas con cadenas como valores. En este caso, considere usar la función serialize() .

Resultados de prueba para matriz multidimensional con md5-hashes (32 caracteres) en claves y valores:

Test name Repeats Result Performance serialize 10000 0.761195 sec +0.00% print_r 10000 1.669689 sec -119.35% json_encode 10000 1.712214 sec -124.94% var_export 10000 1.735023 sec -127.93%

Resultado de la prueba para matriz multidimensional numérica:

Test name Repeats Result Performance json_encode 10000 1.040612 sec +0.00% var_export 10000 1.753170 sec -68.47% serialize 10000 1.947791 sec -87.18% print_r 10000 9.084989 sec -773.04%

Fuente de prueba de matriz asociativa. Fuente de prueba de matriz numérica.


Me estoy uniendo a una fiesta muy concurrida al responder, pero hay una consideración importante que ninguna de las respuestas existentes aborda. El valor de json_encode() y serialize() dependen del orden de los elementos en la matriz.

Estos son los resultados de no clasificar y ordenar las matrices, en dos matrices con valores idénticos pero agregados en un orden diferente (código en la parte inferior de la publicación) :

serialize() 1c4f1064ab79e4722f41ab5a8141b210 1ad0f2c7e690c8e3cd5c34f7c9b8573a json_encode() db7178ba34f9271bfca3a05c5dddf502 c9661c0852c2bd0e26ef7951b4ca9e6f Sorted serialize() 1c4f1064ab79e4722f41ab5a8141b210 1c4f1064ab79e4722f41ab5a8141b210 Sorted json_encode() db7178ba34f9271bfca3a05c5dddf502 db7178ba34f9271bfca3a05c5dddf502

Por lo tanto, los dos métodos que recomendaría para hash una matriz serían:

// You will need to write your own deep_ksort(), or see // my example below md5( serialize(deep_ksort($array)) ); md5( json_encode(deep_ksort($array)) );

La elección de json_encode() o serialize() debe determinarse probando el tipo de datos que está utilizando . Por mis propias pruebas en datos puramente textuales y numéricos, si el código no está ejecutando un ciclo cerrado miles de veces, entonces la diferencia ni siquiera vale la evaluación comparativa. Yo personalmente uso json_encode() para ese tipo de datos.

Aquí está el código usado para generar la prueba de clasificación anterior:

$a = array(); $a[''aa''] = array( ''aaa''=>''AAA'', ''bbb''=>''ooo'', ''qqq''=>''fff'',); $a[''bb''] = array( ''aaa''=>''BBBB'', ''iii''=>''dd'',); $b = array(); $b[''aa''] = array( ''aaa''=>''AAA'', ''qqq''=>''fff'', ''bbb''=>''ooo'',); $b[''bb''] = array( ''iii''=>''dd'', ''aaa''=>''BBBB'',); echo " serialize()/n"; echo md5(serialize($a))."/n"; echo md5(serialize($b))."/n"; echo "/n json_encode()/n"; echo md5(json_encode($a))."/n"; echo md5(json_encode($b))."/n"; $a = deep_ksort($a); $b = deep_ksort($b); echo "/n Sorted serialize()/n"; echo md5(serialize($a))."/n"; echo md5(serialize($b))."/n"; echo "/n Sorted json_encode()/n"; echo md5(json_encode($a))."/n"; echo md5(json_encode($b))."/n";

Mi implementación rápida de deep_ksort () se ajusta a este caso, pero compruébela antes de utilizarla en sus propios proyectos:

/* * Sort an array by keys, and additionall sort its array values by keys * * Does not try to sort an object, but does iterate its properties to * sort arrays in properties */ function deep_ksort($input) { if ( !is_object($input) && !is_array($input) ) { return $input; } foreach ( $input as $k=>$v ) { if ( is_object($v) || is_array($v) ) { $input[$k] = deep_ksort($v); } } if ( is_array($input) ) { ksort($input); } // Do not sort objects return $input; }


Nota importante acerca de serialize()

No recomiendo usarlo como parte de la función hash porque puede devolver resultados diferentes para los siguientes ejemplos. Verifique el ejemplo a continuación:

Ejemplo simple:

$a = new /stdClass; $a->test = ''sample''; $b = new /stdClass; $b->one = $a; $b->two = clone $a;

Produce

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}}"

Pero el siguiente código:

<?php $a = new /stdClass; $a->test = ''sample''; $b = new /stdClass; $b->one = $a; $b->two = $a;

Salida:

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";r:2;}"

Entonces, en lugar del segundo objeto php solo crea el enlace "r: 2". a la primera instancia. Definitivamente es una buena y correcta forma de serializar datos, pero puede llevar a problemas con su función de hash.


Tenga en cuenta que serialize y json_encode actúan de forma diferente cuando se trata de matrices numéricas donde las claves no comienzan en 0 o matrices asociativas. json_encode almacenará dichas matrices como un Object , por lo que json_decode devuelve un Object , donde unserialize devolverá una matriz con exactamente las mismas claves.


hay varias respuestas que dicen usar json_code,

pero json_encode no funciona bien con la cadena iso-8859-1, tan pronto como haya un carácter especial, la cadena se recorta.

recomendaría usar var_export:

md5(var_export($array, true))

no tan lento como serializar, no tan bugged como json_encode


(Función de copiar y pegar en la parte inferior)

Como se mencionó anteriormente, lo siguiente funcionará.

md5(serialize($array));

Sin embargo, vale la pena señalar que (irónicamente) json_encode realiza notablemente más rápido:

md5(json_encode($array));

De hecho, el aumento de velocidad es doble aquí ya que (1) json_encode solo realiza más rápido que serializar, y (2) json_encode produce una cadena más pequeña y, por lo tanto, menos para md5.

Editar: Aquí hay evidencia para apoyar esta afirmación:

<?php //this is the array I''m using -- it''s multidimensional. $array = unserialize(''a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:4:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}i:3;a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}''); //The serialize test $b4_s = microtime(1); for ($i=0;$i<10000;$i++) { $serial = md5(serialize($array)); } echo ''serialize() w/ md5() took: ''.($sTime = microtime(1)-$b4_s).'' sec<br/>''; //The json test $b4_j = microtime(1); for ($i=0;$i<10000;$i++) { $serial = md5(json_encode($array)); } echo ''json_encode() w/ md5() took: ''.($jTime = microtime(1)-$b4_j).'' sec<br/><br/>''; echo ''json_encode is <strong>''.( round(($sTime/$jTime)*100,1) ).''%</strong> faster with a difference of <strong>''.($sTime-$jTime).'' seconds</strong>'';

JSON_ENCODE es consistentemente más del 250% (2.5x) más rápido (a menudo más del 300%); esta no es una diferencia trivial. Puede ver los resultados de la prueba con este script en vivo aquí:

Ahora, una cosa a tener en cuenta es que la matriz (1,2,3) producirá una MD5 diferente como matriz (3,2,1). Si esto NO es lo que quieres Pruebe el siguiente código:

//Optionally make a copy of the array (if you want to preserve the original order) $original = $array; array_multisort($array); $hash = md5(json_encode($array));

Editar: Ha habido algunas dudas sobre si revertir la orden produciría los mismos resultados. Entonces, he hecho eso ( correctamente ) aquí:

Como puede ver, los resultados son exactamente los mismos. Aquí está la prueba ( corregida ) originalmente creada por alguien relacionado con Drupal :

Y para una buena medida, aquí hay una función / método que puede copiar y pegar (probado en 5.3.3-1ubuntu9.5):

function array_md5(Array $array) { //since we''re inside a function (which uses a copied array, not //a referenced array), you shouldn''t need to copy the array array_multisort($array); return md5(json_encode($array)); }


Actualmente la respuesta más md5(serialize($array)); no funciona bien con los objetos.

Considera el código:

$a = array(new /stdClass()); $b = array(new /stdClass());

Aunque las matrices son diferentes (contienen diferentes objetos), tienen el mismo hash al usar md5(serialize($array)); . ¡Entonces tu hash es inútil!

Para evitar ese problema, puede reemplazar objetos con el resultado de spl_object_hash() antes de la serialización. También debe hacerlo recursivamente si su matriz tiene múltiples niveles.

El código a continuación también clasifica matrices por claves, como han sugerido dotancohen.

function replaceObjectsWithHashes(array $array) { foreach ($array as &$value) { if (is_array($value)) { $value = $this->replaceObjectsInArrayWithHashes($value); } elseif (is_object($value)) { $value = spl_object_hash($value); } } ksort($array); return $array; }

Ahora puede usar md5(serialize(replaceObjectsWithHashes($array))) .

(Tenga en cuenta que la matriz en PHP es el tipo de valor. Así que la función replaceObjectsWithHashes NO cambia la matriz original).


// Convert nested arrays to a simple array $array = array(); array_walk_recursive($input, function ($a) use (&$array) { $array[] = $a; }); sort($array); $hash = md5(json_encode($array)); ---- These arrays have the same hash: $arr1 = array(0 => array(1, 2, 3), 1, 2); $arr2 = array(0 => array(1, 3, 2), 1, 2);


md5(serialize($array));


md5(serialize($array));

Funcionará, pero el hash cambiará dependiendo del orden de la matriz (aunque eso no importa).