(Функция копирования и вставки внизу)
Как упоминалось ранее, следующее будет работать.
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%) - это нетривиальная разница. Вы можете увидеть результаты теста с этим живым скриптом здесь:
Теперь следует отметить одну вещь: array (1,2,3) создаст другой MD5 как array (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));
Изменить: возник вопрос, приведет ли изменение порядка к тем же результатам. Итак, я сделал это ( правильно ) здесь:
Как видите, результаты точно такие же. Вот ( исправленный ) тест, изначально созданный кем-то связанным с 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));
}
serialize() w/ md5() took: 0.27773594856262 sec
json_encode() w/ md5() took: 0.34809803962708 sec
json_encode is (79.8%) faster with a difference of (-0.070362091064453 seconds)
(расчет процента явно неверно). Мой массив имеет глубину до 2 уровней, поэтому просто имейте в виду, что (как обычно) ваш пробег может отличаться.источник
Я присоединяюсь к очень многолюдной вечеринке, отвечая, но есть важное соображение, которого нет ни в одном из сохранившихся ответов. Значение
json_encode()
иserialize()
оба зависят от порядка элементов в массиве!Вот результаты отсутствия сортировки и сортировки массивов на двух массивах с одинаковыми значениями, но добавленными в другом порядке (код внизу сообщения) :
Поэтому два метода, которые я бы рекомендовал для хеширования массива, были бы:
Выбор
json_encode()
илиserialize()
должен определяться путем тестирования типа данных, которые вы используете . По моему собственному тестированию на чисто текстовых и числовых данных, если код не запускает жесткий цикл тысячи раз, то разница даже не стоит сравнивать. Я лично используюjson_encode()
для этого тип данных.Вот код, использованный для генерации теста сортировки выше:
Моя быстрая реализация deep_ksort () подходит для этого случая, но проверьте ее перед использованием в своих проектах:
источник
Ответ сильно зависит от типов данных значений массива. Для больших струн используйте:
Для коротких строк и целых чисел используйте:
4 встроенные функции PHP могут преобразовывать массив в строку: serialize () , json_encode () , var_export () , print_r () .
Результаты тестирования многомерного массива с md5-хешами (32 символа) в ключах и значениях:
Результат теста для числового многомерного массива:
Источник теста ассоциативного массива . Источник теста числового массива .
источник
Помимо отличного ответа Брока (+1), любая достойная библиотека хеширования позволяет вам обновлять хэш с приращением, поэтому вы должны иметь возможность обновлять каждую строку последовательно, вместо того, чтобы создавать одну гигантскую строку.
Видеть:
hash_update
источник
Будет работать, но хеш будет меняться в зависимости от порядка массива (хотя это может не иметь значения).
источник
Обратите внимание на это
serialize
иjson_encode
действуйте иначе, когда дело касается числовых массивов, где ключи не начинаются с 0, или ассоциативных массивов.json_encode
будет хранить такие массивы какObject
, поэтомуjson_decode
возвращаетObject
, гдеunserialize
вернет массив с точно такими же ключами.источник
Думаю, это может быть хорошим советом:
источник
Важное примечание о
serialize()
Я не рекомендую использовать его как часть функции хеширования, потому что он может возвращать другой результат для следующих примеров. Посмотрите пример ниже:
Простой пример:
Производит
Но следующий код:
Вывод:
Поэтому вместо второго объекта php просто создайте ссылку "r: 2;" в первую инстанцию. Это определенно хороший и правильный способ сериализации данных, но он может привести к проблемам с вашей функцией хеширования.
источник
источник
есть несколько ответов, говорящих об использовании json_code,
но json_encode не работает нормально со строкой iso-8859-1, как только есть специальный char, строка обрезается.
я бы посоветовал использовать var_export:
не так медленно, как сериализация, не так глючит, как json_encode
источник
В настоящее время ответ, получивший наибольшее количество голосов
md5(serialize($array));
, не работает с объектами.Рассмотрим код:
Несмотря на то, что массивы разные (они содержат разные объекты), при использовании они имеют одинаковый хэш
md5(serialize($array));
. Значит, ваш хеш бесполезен!Чтобы избежать этой проблемы, вы можете заменить объекты на результат
spl_object_hash()
до сериализации. Вы также должны делать это рекурсивно, если ваш массив имеет несколько уровней.Код ниже также сортирует массивы по ключам, как предложил дотанкоэн.
Теперь можно использовать
md5(serialize(replaceObjectsWithHashes($array)))
.(Обратите внимание, что массив в PHP имеет тип значения. Поэтому
replaceObjectsWithHashes
функция НЕ изменяет исходный массив.)источник
Я не так легко увидел решение выше, поэтому я хотел предложить более простой ответ. Для меня я получал тот же ключ, пока не использовал ksort (сортировка ключей):
Сначала отсортировано с помощью Ksort, затем выполняется sha1 для json_encode:
пример:
Вывод измененных массивов и хешей:
источник