MD5 다차원 어레이에 대한 PHP의 최선의 방법?

다차원 어레이의 MD5(또는 기타 해시)를 생성하는 가장 좋은 방법은 무엇입니까?

어레이의 각 레벨을 통과하는 루프를 간단하게 작성할 수 있었습니다.각 값을 문자열로 연결하여 문자열로 MD5를 실행하는 것만으로 충분했습니다.

다만, 이것은 기껏해야 번거로울 것 같아서, 다차원 배열을 취해 해시하는 펑키한 함수는 없을까 하고 생각했습니다.



질문에 대한 답변



(하단의 복사-n-붙여넣기 가능 기능)

전술한 바와 같이, 이하가 유효합니다.

md5(serialize($array)); 

단, (아이러니컬하게도) json_encode의 처리속도는 현저하게 빨라집니다.

md5(json_encode($array)); 

(1) json_encode만 serialize보다 고속으로 동작하고 (2) json_encode는 더 작은 문자열을 생성하므로 md5가 처리할 수 있는 속도가 2배 향상됩니다.

편집: 다음은 이 주장을 뒷받침하는 증거입니다.

<?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% 이상). 이는 사소한 차이가 아닙니다.다음 라이브 스크립트를 사용하여 테스트 결과를 확인할 수 있습니다.

여기서 주의할 점은 어레이(1, 2, 3)는 어레이(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)); 

편집: 순서를 번복하는 것이 같은 결과를 가져올 수 있는지에 대해서는 몇 가지 의문이 있습니다.그래서 (정확하게) 여기서 했습니다.

보시다시피 결과는 똑같습니다.이것은 Drupal과 관련된 사람이 만든 (수정된) 테스트입니다.

또한 복사하여 붙여넣을 수 있는 기능/방법을 소개합니다(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)); 



저는 매우 혼잡한 파티에 답변으로 참석합니다만, 현존하는 답변 중 어느 것도 다루지 않는 중요한 고려사항이 있습니다.및 둘 다 배열 내 요소의 순서에 따라 달라집니다.

값은 같지만 순서가 다른 2개의 어레이(포스트 하단의 코드)에서 어레이를 정렬 및 정렬하지 않은 결과를 다음에 나타냅니다.


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-hash(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)을 제외하고, 적당한 해시 라이브러리를 사용하면 해시를 증분 업데이트할 수 있으므로 각 문자열로 순차적으로 업데이트할 수 있으며, 대신 하나의 거대한 문자열을 구축해야 합니다.

참조: