PHP最好的MD5多维数组方式?

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)

  • 大声笑!真?我投票赞成"过度"优化?实际上,PHP的序列化速度要慢得多.我会用证据更新我的答案...... (47认同)
  • 内森在这里所做的事情是有价值的,即使人们看不到它的价值.在我们的上下文之外的某些情况下,它可能是有价值的优化.微优化在一些但不是所有情况下都是一个糟糕的决定 (19认同)
  • 我不是为了它而进行微优化的人,但是如果没有额外的工作有记录的性能增加,那么为什么不使用它. (13认同)
  • 好吧,我不明白为什么Nathan的答案不是最佳答案.说真的,使用序列化并用一个非常慢的网站骚扰你的用户.Epic +1 @ NathanJ.Brauer! (3认同)
  • 我不是在拖钓. (2认同)
  • 实际上,它看起来取决于阵列的深度.我碰巧需要一些需要尽可能快地运行的东西,而你的POC显示json_encode()快了约300%,当我将代码中的$ array变量更改为我的用例时,它返回`serialize() w/md5()采取:0.27773594856262秒``json_encode()w/md5()采取:0.34809803962708秒``json_encode更快(79.8%),差异为(-0.070362091064453秒)`(precent计算明显不正确) .我的阵列深达2级,所以请记住(像往常一样)你的milage可能会有所不同. (2认同)

Bro*_*ell 168

md5(serialize($array));
Run Code Online (Sandbox Code Playgroud)

  • 如果由于某种原因你想要匹配哈希(指纹)你可能想要考虑对数组"排序"或"ksort"进行排序,另外可能还需要实施某种擦洗/清理 (12认同)
  • 序列化比第二个答案的json_encode慢得多.让您的服务器愉快并使用json_encode!:) (9认同)
  • 看起来您需要对自己的数组进行基准测试,以确定是否应该使用json_encode或serialize.根据阵列的不同而不同. (3认同)

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)

  • 非常好的补充上述答案+1 (3认同)

Ale*_*ruk 9

答案在很大程度上取决于数组值的数据类型.对于大字符串使用:

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)

关联数组测试源.数字数组测试源.


Chr*_*ung 7

除了Brock的优秀答案(+1)之外,任何体面的散列库都允许您以增量方式更新散列,因此您应该能够按顺序更新每个字符串,而不必构建一个巨大的字符串.

看到: hash_update