(Funkcja kopiowania i wklejania na dole)
Jak wspomniano wcześniej, poniższe będą działać.
md5(serialize($array));
Warto jednak zauważyć, że (jak na ironię) json_encode działa zauważalnie szybciej:
md5(json_encode($array));
W rzeczywistości wzrost szybkości jest tutaj dwukrotny, ponieważ (1) sam json_encode działa szybciej niż serialize, a (2) json_encode generuje mniejszy ciąg, a zatem mniejszy dla md5.
Edycja: Oto dowody na poparcie tego twierdzenia:
<?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 jest konsekwentnie ponad 250% (2,5x) szybsze (często ponad 300%) - to nie jest trywialna różnica. Możesz zobaczyć wyniki testu z tym skryptem na żywo tutaj:
Jedną rzeczą wartą uwagi jest to, że array (1,2,3) wyprodukuje inne MD5 niż array (3,2,1). Jeśli to NIE jest to, czego chcesz. Wypróbuj następujący kod:
//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));
Edycja: pojawiło się pytanie, czy odwrócenie kolejności dałoby takie same wyniki. Więc zrobiłem to ( poprawnie ) tutaj:
Jak widać, wyniki są dokładnie takie same. Oto ( poprawiony ) test pierwotnie stworzony przez kogoś związanego z Drupalem :
I na dokładkę, oto funkcja / metoda, którą możesz skopiować i wkleić (przetestowana w 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)
(obliczenie precent jest oczywiście błędny). Moja tablica ma do 2 poziomów głębokości, więc pamiętaj, że (jak zwykle) Twój przebieg może się różnić.źródło
Odpowiadam na bardzo zatłoczoną imprezę, ale należy wziąć pod uwagę, że żadna z istniejących odpowiedzi nie dotyczy. Wartość
json_encode()
iserialize()
obie zależą od kolejności elementów w tablicy!Oto wyniki braku sortowania i sortowania tablic na dwóch tablicach z identycznymi wartościami, ale dodanymi w innej kolejności (kod na dole postu) :
Dlatego dwie metody, które poleciłbym do haszowania tablicy , to:
Wybór
json_encode()
lubserialize()
należy określić, testując typ danych, których używasz . Na podstawie moich własnych testów na danych czysto tekstowych i liczbowych, jeśli kod nie wykonuje ciasnej pętli tysiące razy, różnica nie jest nawet warta porównania. Osobiście używamjson_encode()
do tego typu danych.Oto kod użyty do wygenerowania powyższego testu sortowania:
Moja szybka implementacja deep_ksort () pasuje do tego przypadku, ale sprawdź to przed użyciem we własnych projektach:
źródło
Odpowiedź w dużym stopniu zależy od typów danych wartości tablicowych. Do dużych strun użyj:
Dla krótkich ciągów i liczb całkowitych użyj:
4 wbudowane funkcje PHP mogą przekształcić tablicę w łańcuch znaków: serialize () , json_encode () , var_export () , print_r () .
Wyniki testu dla wielowymiarowej tablicy z hashami md5 (32 znaki) w kluczach i wartościach:
Wynik testu dla wielowymiarowej tablicy numerycznej:
Źródło testu tablicy asocjacyjnej . Numeryczne źródło testu tablicy .
źródło
Oprócz doskonałej odpowiedzi Brocka (+1), każda przyzwoita biblioteka haszująca umożliwia aktualizowanie skrótu w przyrostach, więc powinieneś być w stanie aktualizować każdy ciąg sekwencyjnie, zamiast tworzyć jeden gigantyczny ciąg.
Widzieć:
hash_update
źródło
Będzie działać, ale wartość skrótu będzie się zmieniać w zależności od kolejności tablicy (choć może to nie mieć znaczenia).
źródło
Zauważ to
serialize
ijson_encode
zachowuj się inaczej, jeśli chodzi o tablice numeryczne, w których klucze nie zaczynają się od 0, lub tablice asocjacyjne.json_encode
zapisze takie tablice jako anObject
, więcjson_decode
zwraca anObject
, gdzieunserialize
zwróci tablicę z dokładnie tymi samymi kluczami.źródło
Myślę, że to może być dobra wskazówka:
źródło
Ważna uwaga dotycząca
serialize()
Nie polecam używania go jako części funkcji haszującej, ponieważ może zwrócić różne wyniki dla poniższych przykładów. Sprawdź poniższy przykład:
Prosty przykład:
Produkuje
Ale następujący kod:
Wynik:
Więc zamiast drugiego obiektu php po prostu utwórz link "r: 2;" do pierwszej instancji. Jest to zdecydowanie dobry i poprawny sposób serializacji danych, ale może to prowadzić do problemów z funkcją haszowania.
źródło
źródło
jest kilka odpowiedzi mówiących o używaniu json_code,
ale json_encode nie działa dobrze z ciągiem iso-8859-1, gdy tylko pojawi się specjalny znak, ciąg jest przycinany.
radziłbym skorzystać z var_export:
nie tak powolny jak serializowanie, nie tak bugowany jak json_encode
źródło
Obecnie najbardziej
md5(serialize($array));
pozytywna odpowiedź nie działa dobrze z obiektami.Rozważ kod:
Mimo że tablice są różne (zawierają różne obiekty), mają ten sam skrót podczas używania
md5(serialize($array));
. Więc twój haszysz jest bezużyteczny!Aby uniknąć tego problemu, możesz zastąpić obiekty wynikiem
spl_object_hash()
przed serializacją. Powinieneś to również zrobić rekurencyjnie, jeśli twoja tablica ma wiele poziomów.Poniższy kod również sortuje tablice według kluczy, zgodnie z sugestią dotancohen.
Teraz możesz użyć
md5(serialize(replaceObjectsWithHashes($array)))
.(Zauważ, że tablica w PHP jest typu wartości. Więc
replaceObjectsWithHashes
funkcja NIE zmienia oryginalnej tablicy.)źródło
Powyżej nie widziałem rozwiązania tak łatwo, więc chciałem podać prostszą odpowiedź. U mnie otrzymywałem ten sam klucz, dopóki nie użyłem ksort (sortowanie kluczy):
Najpierw posortowano za pomocą Ksort, a następnie wykonano sha1 na json_encode:
przykład:
Wyjście zmienionych tablic i skrótów:
źródło