2013-02-10 7 views
12
$array = array(1, '1a', '1'); 
var_export(array_unique($array, SORT_REGULAR)); 
  • Das Ergebnis: array (0 => 1, 2 => '1')
  • In dem PHP-Handbuch: SORT_REGULAR - Vergleichen Produkte normalerweise (nicht Typen ändern).

Was ist die Logik dahinter? Warum oder wie ist "1a" ausgeschlossen?array_unique SORT_REGULAR flag

Antwort

13

Dies geschieht, weil array_unique Arbeiten von first sorting the values as strings, dann iterating über die sortierten Array und für jeden Wert von dem Ergebnis ohne alle aufeinanderfolgenden Werte, die es gleich vergleichen.

Die Vergleichsfunktion für "Vergleich gleich" oben wird gemäß dem zweiten Parameter ausgewählt, der für SORT_REGULAR mit einer Gleichheitsprüfung mit == identisch ist.

Dieses Verhalten führt zu einer ganzen Reihe von Problemen. Da die Sortierung Quicksort ist, ist es instabil. Daher gibt das Sortieren eines Arrays, das sowohl 1 als auch '1' enthält, keine Garantie dafür, welche davon am Anfang im Ergebnis stehen wird. Dies bedeutet, dass in manchen Fällen willkürlich "1" und in anderen Fällen '1' vorkommt.

Doch der Wahnsinn geht weiter: die Ansicht, dass, wenn die Sorte produziert [1, '1', '1a'] dann '1a'nicht im Ergebnis enthalten sein (es vergleicht gleich 1), während, wenn die Art produziert ['1', 1, '1a'] es wird dann enthalten sein (es tut nicht gleich der Zeichenkette '1')!

+0

Erfolgt diese Iteration nur einmal? Denn dann sollten wir doppelte Werte bekommen, wenn eine andere '1' nach' 5' eingefügt wird. –

+0

@OneTrickPony: Ich habe nicht explizit erwähnt, dass das Array zuerst sortiert wird (die Dokumentation tut das). Aber auf den zweiten Gedanken ist es ziemlich wichtig, weil die Art nicht stabil ist (Quicksort), also lassen Sie mich die Antwort ein wenig erweitern. – Jon

+0

@OneTrickPony: Eigentlich funktioniert es ein bisschen anders als das, was ich glaubte - und Sie werden wahrscheinlich nicht überrascht sein zu wissen, dass das Verhalten in solchen Fällen nicht vorhergesagt werden kann, weil, nun, PHP. – Jon

4

Wenn Sie ein wenig technischer werden möchten, können Sie die Quelle sehen.

Das Flag PHP_SORT_REGULAR sagt einfach array_unique, um auf den Standardvergleichsoperator (==) zurückzugreifen.

Sie können diese sehen in der Quelle für array_unique die php_set_compare_func verwendet:

static void php_set_compare_func(int sort_type TSRMLS_DC) /* {{{ */ 
{ 
switch (sort_type & ~PHP_SORT_FLAG_CASE) { 
... 
    case PHP_SORT_REGULAR: 
    default: 
     ARRAYG(compare_func) = compare_function; 
     break; 
} 

Wo compare_func nur die standard comparison function ist.

Es ist wahrscheinlich ein Dokumentationsfehler mehr als alles andere. Der Kommentar in der Dokumentation ist ein wenig irreführend:

... gleich, wenn und nur wenn (string) $ elem1 === (string) $ elem2

Wenn beide Werte in Strings gegossen , dann ist die === unnötig, aber es führt zu der Annahme, dass SORT_REGULAR einen Typenvergleich durchführt.