Pet*_*ohn 110 php arrays hash md5 multidimensional-array
生成多维数组的MD5(或任何其他哈希)的最佳方法是什么?
我可以轻松地编写一个循环,遍历数组的每个级别,将每个值连接成一个字符串,然后简单地在字符串上执行MD5.
然而,这看起来很麻烦,我想知道是否有一个时髦的函数,它将采用一个多维数组,并哈希它.
Nat*_*.B. 240
(底部的复制粘贴功能)
如前所述,以下内容将起作用.
md5(serialize($array));
Run Code Online (Sandbox Code Playgroud)
但是,值得注意的是(具有讽刺意味的是)json_encode的执行速度明显更快:
md5(json_encode($array));
Run Code Online (Sandbox Code Playgroud)
事实上,速度增加在这里是两倍,因为(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>';
Run Code Online (Sandbox Code Playgroud)
JSON_ENCODE持续超过250%(2.5倍)(通常超过300%) - 这不是一个微不足道的差异.您可以在此处看到此实时脚本的测试结果:
现在,有一点需要注意的是,数组(1,2,3)将产生一个不同的MD5作为数组(3,2,1). 如果这不是你想要的.请尝试以下代码:
//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));
Run Code Online (Sandbox Code Playgroud)
编辑:关于逆转订单是否会产生相同的结果存在一些问题.所以,我在这里做了(正确):
如您所见,结果完全相同.这是最初由与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));
}
Run Code Online (Sandbox Code Playgroud)
Bro*_*ell 168
md5(serialize($array));
Run Code Online (Sandbox Code Playgroud)
dot*_*hen 25
我通过回答加入了一个非常拥挤的聚会,但有一个重要的考虑因素是现存的答案都没有解决.值json_encode()
和serialize()
都取决于数组中元素的顺序!
以下是不对数组进行排序和排序的结果,两个数组具有相同的值,但以不同的顺序添加 (帖子底部的代码):
serialize()
1c4f1064ab79e4722f41ab5a8141b210
1ad0f2c7e690c8e3cd5c34f7c9b8573a
json_encode()
db7178ba34f9271bfca3a05c5dddf502
c9661c0852c2bd0e26ef7951b4ca9e6f
Sorted serialize()
1c4f1064ab79e4722f41ab5a8141b210
1c4f1064ab79e4722f41ab5a8141b210
Sorted json_encode()
db7178ba34f9271bfca3a05c5dddf502
db7178ba34f9271bfca3a05c5dddf502
Run Code Online (Sandbox Code Playgroud)
因此,我建议散列数组的两种方法是:
// 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)) );
Run Code Online (Sandbox Code Playgroud)
选择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";
Run Code Online (Sandbox Code Playgroud)
我的快速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;
}
Run Code Online (Sandbox Code Playgroud)
答案在很大程度上取决于数组值的数据类型.对于大字符串使用:
md5(serialize($array));
Run Code Online (Sandbox Code Playgroud)
对于短字符串和整数使用:
md5(json_encode($array));
Run Code Online (Sandbox Code Playgroud)
4个内置的PHP函数可以将数组转换为字符串: serialize(),json_encode(),var_export(),print_r().
注意: json_encode()函数在处理以字符串作为值的关联数组时会变慢.在这种情况下,请考虑使用serialize()函数.
在键和值中使用md5-hashes(32 char)测试多维数组的结果:
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%
Run Code Online (Sandbox Code Playgroud)
数值多维数组的测试结果:
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%
Run Code Online (Sandbox Code Playgroud)