다차원 배열의 MD5 (또는 다른 해시)를 생성하는 가장 좋은 방법은 무엇입니까?
배열의 각 수준을 가로 질러 각 값을 문자열로 연결하고 단순히 문자열에서 MD5를 수행하는 루프를 쉽게 작성할 수 있습니다.
그러나 이것은 기껏해야 번거로운 것처럼 보이며 다차원 배열을 가져와 해시하는 펑키 함수가 있는지 궁금했습니다.
답변
(하단에 복사 및 붙여 넣기 기능)
앞에서 언급했듯이 다음이 작동합니다.
md5(serialize($array));
그러나 (아이러니하게도) json_encode가 눈에 띄게 더 빠르게 수행된다는 점은 주목할 가치가 있습니다 .
md5(json_encode($array));
사실, 여기서 속도 증가는 (1) json_encode 단독으로 직렬화보다 빠르게 수행되고 (2) json_encode가 더 작은 문자열을 생성하므로 md5가 처리 할 수 없기 때문에 두 배입니다.
편집 : 이 주장을 뒷받침하는 증거는 다음과 같습니다.
<?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는 지속적으로 250 % (2.5 배) 더 빠릅니다 (종종 300 % 이상). 이는 사소한 차이가 아닙니다. 여기에서이 라이브 스크립트로 테스트 결과를 볼 수 있습니다.
- http://nathanbrauer.com/playground/serialize-vs-json.php
- http://nathanbrauer.com/playground/plain-text/serialize-vs-json.php
이제 한 가지 주목할 점은 array (1,2,3)이 array (3,2,1)과 다른 MD5를 생성한다는 것입니다. 이것이 당신이 원하는 것이 아니라면 . 다음 코드를 시도하십시오.
//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));
편집 : 주문을 취소하면 동일한 결과가 생성되는지 여부에 대한 질문이있었습니다. 그래서 여기에서 ( 올바르게 ) 수행했습니다 .
- http://nathanbrauer.com/playground/json-vs-serialize.php
- http://nathanbrauer.com/playground/plain-text/json-vs-serialize.php
보시다시피 결과는 정확히 동일합니다. 다음은 원래 Drupal과 관련된 누군가가 만든 ( 수정 된 ) 테스트입니다 .
- http://nathanjbrauer.com/playground/drupal-calculation.php
- http://nathanjbrauer.com/playground/plain-text/drupal-calculation.php
그리고 좋은 측정을 위해 다음은 복사하여 붙여 넣을 수있는 함수 / 메서드입니다 (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));
}
답변
md5(serialize($array));
답변
나는 응답으로 매우 붐비는 파티에 참여하고 있지만 현존하는 응답 중 어느 것도 언급하지 않는다는 중요한 고려 사항이 있습니다. 의 값 json_encode()
과 serialize()
둘 다 배열의 요소 순서에 따라 달라집니다!
다음은 값이 동일하지만 다른 순서로 추가 된 두 배열 에서 배열을 정렬 및 정렬하지 않은 결과입니다 (게시물 하단의 코드) .
serialize()
1c4f1064ab79e4722f41ab5a8141b210
1ad0f2c7e690c8e3cd5c34f7c9b8573a
json_encode()
db7178ba34f9271bfca3a05c5dddf502
c9661c0852c2bd0e26ef7951b4ca9e6f
Sorted serialize()
1c4f1064ab79e4722f41ab5a8141b210
1c4f1064ab79e4722f41ab5a8141b210
Sorted json_encode()
db7178ba34f9271bfca3a05c5dddf502
db7178ba34f9271bfca3a05c5dddf502
따라서 배열 을 해시하는 데 권장하는 두 가지 방법 은 다음과 같습니다.
// 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)) );
의 선택 json_encode()
이상이 serialize()
되어야 하는 데이터의 종류에 테스트에 의해 결정 당신이 사용하고 있습니다 . 순전히 텍스트 및 숫자 데이터에 대한 자체 테스트를 통해 코드가 타이트한 루프를 수천 번 실행하지 않으면 그 차이는 벤치마킹 할 가치가 없습니다. 나는 개인적 json_encode()
으로 그러한 유형의 데이터를 사용합니다.
위의 정렬 테스트를 생성하는 데 사용되는 코드는 다음과 같습니다.
$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";
내 빠른 deep_ksort () 구현은이 경우에 적합하지만 자신의 프로젝트에서 사용하기 전에 확인하십시오.
/*
* 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;
}
답변
대답은 배열 값의 데이터 유형에 따라 크게 달라집니다. 큰 문자열의 경우 다음을 사용하십시오.
md5(serialize($array));
짧은 문자열 및 정수의 경우 다음을 사용하십시오.
md5(json_encode($array));
4 개의 내장 PHP 함수가 배열을 문자열로 변환 할 수 있습니다 :
serialize () , json_encode () , var_export () , print_r () .
주의 : json_encode () 함수는 문자열이있는 연관 배열을 값으로 처리하는 동안 속도가 느려집니다. 이 경우 serialize () 함수 사용을 고려하십시오 .
키와 값에 md5 해시 (32 자)가있는 다차원 배열에 대한 테스트 결과 :
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%
숫자 형 다차원 배열에 대한 테스트 결과 :
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%
답변
Brock의 훌륭한 답변 (+1) 외에도 괜찮은 해싱 라이브러리를 사용하면 해시를 증분 업데이트 할 수 있으므로 하나의 거대한 문자열을 구축하는 대신 각 문자열을 순차적으로 업데이트 할 수 있어야합니다.
보다: hash_update
답변
md5(serialize($array));
작동하지만 해시는 배열의 순서에 따라 변경됩니다 (중요하지 않을 수도 있음).
답변
주의 serialize
와 json_encode
그 키가 0에서 시작하지 않는 숫자 배열, 또는 연관 배열에 올 때 다르게 행동한다.
json_encode
이러한 배열을로 저장 Object
하므로를 json_decode
반환합니다 Object
. 여기서는 unserialize
정확히 동일한 키를 가진 배열을 반환합니다.
