2013-02-10 14 views
12
$array = array(1, '1a', '1'); 
var_export(array_unique($array, SORT_REGULAR)); 
  • Il risultato: array (0 => 1, 2 => '1')
  • Nel manuale PHP: SORT_REGULAR - confronta articoli normalmente (non modificare i tipi).

Qual è la logica dietro questo? Perché o come viene esclusa la '1a'?array_unique SORT_REGULAR bandiera

risposta

13

Ciò accade perché array_unique opere first sorting the values as strings, quindi iterating sulla matrice ordinata e per ogni valore escludendo dal risultato tutti i valori successivi che risultano uguali ad esso.

La funzione di comparazione per "confronto uguali" sopra viene scelto in base al secondo parametro, che per SORT_REGULAR è la stessa di un controllo di parità con ==.

Questo comportamento genera un sacco di trucchi. Dato che l'ordinamento è quicksort, è instabile. Pertanto, l'ordinamento di una matrice che contiene sia 1 e '1' non garantisce che si finisce per essere il primo risultato. Ciò significa che array_unique potrebbe sembrare arbitrariamente "preferire" 1 in alcuni casi e '1' in altri.

Tuttavia la follia continua: considerare che se il genere produce [1, '1', '1a'] poi '1a' sarà non essere inclusi nel risultato (confronta pari a 1) mentre se il tipo produce ['1', 1, '1a'] allora sarà essere inclusi (lo fa non confrontare uguale alla stringa '1')!

+0

Questa iterazione si verifica solo una volta? Perché allora dovremmo ottenere valori duplicati se è incluso un altro '1' dopo' 5' –

+0

@OneTrickPony: non ho menzionato esplicitamente che l'array è ordinato per primo (la documentazione lo fa). Ma a pensarci bene è abbastanza importante perché l'ordinamento non è stabile (quicksort), quindi permettimi di espandere un po 'la risposta. – Jon

+0

@OneTrickPony: In realtà funziona un po 'diverso da quello che credevo - e probabilmente non sarai sorpreso di sapere che il comportamento non può essere previsto in casi come questo perché, beh, PHP. – Jon

4

Se si desidera ottenere un po 'più tecnico, è possibile vedere la fonte.

Il flag PHP_SORT_REGULAR indica semplicemente a array_unique di tornare all'operatore di confronto standard (==).

Potete vedere questo nel sorgente per array_unique che utilizza php_set_compare_func:

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; 
} 

Dove compare_func è solo il standard comparison function.

È probabilmente un errore di documentazione più di ogni altra cosa. Il commento nella documentazione è un po 'fuorviante:

... uguali se e solo se (string) $ elem1 === (string) $ elem2

Se entrambi i valori sono espressi in stringhe , quindi lo === non è necessario, ma presuppone che SORT_REGULAR esegua un confronto tra tipi.

Problemi correlati