Algoritmo di sorting naturale in PHP con supporto per Unicode?

È ansible ordinare un arrays con caratteri Unicode / UTF-8 in PHP utilizzando un algorithm di ordine naturale? Ad esempio (l'ordine in questo arrays è correttamente ordinato):

$arrays = arrays ( 0 => 'Agile', 1 => 'Ágile', 2 => 'Àgile', 3 => 'Âgile', 4 => 'Ägile', 5 => 'Ãgile', 6 => 'Test', ); 

Se provo con asort ($ arrays) ottengo il seguente risultato:

 Array ( [0] => Agile [6] => Test [2] => Àgile [1] => Ágile [3] => Âgile [5] => Ãgile [4] => Ägile ) 

E usando natsort ($ arrays):

 Array ( [2] => Àgile [1] => Ágile [3] => Âgile [5] => Ãgile [4] => Ägile [0] => Agile [6] => Test ) 

Come posso implementare una function che restituisce l'ordine dei risultati corretto (0, 1, 2, 3, 4, 5, 6) in PHP 5? Tutte le funzioni string multi byte (mbstring, iconv, …) sono disponibili sul mio sistema.

EDIT: voglio natsort () i valori, non le chiavi – l'unico motivo per cui sto definendo esplicitamente le chiavi (e usando asort () invece di sort ()) è quello di facilitare il lavoro di scoprire where l' sorting i valori unicode sono andati storto.

La domanda non è così facile da rispondere come sembra al primo sguardo. Questa è una delle aree in cui la mancanza di supporto Unicode di PHP ti colpisce con tutta la forza.

Il primo di tutto natsort() come suggerito da altri poster non ha nulla a che fare con l'sorting di matrici del tipo che si desidera ordinare. Quello che stai cercando è un meccanismo di sorting basato sulle impostazioni locali poiché le stringhe di sorting con caratteri estesi sono sempre una questione della lingua utilizzata. Prendiamo ad esempio il tedesco: A e A possono a volte essere ordinati come se fossero la stessa lettera (DIN 5007/1), e talvolta Ä può essere ordinato in quanto era in effetti "AE" (DIN 5007/2). In svedese, al contrario, arriva alla fine dell'alfabeto.

Se non usi Windows, sei fortunato perché PHP fornisce alcune funzioni esattamente a questo. Usando una combinazione di setlocale() , usort() , strcoll() e le strcoll() internazionali UTF-8 corrette per la tua lingua, ottieni qualcosa di simile a questo:

 $arrays = arrays('Àgile', 'Ágile', 'Âgile', 'Ãgile', 'Ägile', 'Agile', 'Test'); $oldLocal = setlocale(LC_COLLATE, '<<your_RFC1766_language_code>>.utf8'); usort($arrays, 'strcoll'); setlocale(LC_COLLATE, $oldLocal); 

Si noti che è obbligatorio utilizzare la variante locale UTF-8 per ordinare le stringhe UTF-8. Ho resettato la localizzazione nell'esempio sopra al suo valore originale come l'impostazione di una localizzazione usando setlocale() può introdurre effetti collaterali in altri script PHP in esecuzione – per ulteriori dettagli vedere il manuale di PHP.

Quando si utilizza una macchina Windows, al momento non esiste una soluzione a questo problema e non ci sarà prima di PHP 6. Per favore, vedi la mia domanda su SO che prende di mira questo specifico problema.

Azzeccato!

 $arrays = arrays('Ägile', 'Ãgile', 'Test', 'カタカナ', 'かたかな', 'Ágile', 'Àgile', 'Âgile', 'Agile'); function Sortify($string) { return preg_replace('~&([az]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|tilde|uml);~i', '$1' . chr(255) . '$2', htmlentities($string, ENT_QUOTES, 'UTF-8')); } arrays_multisort(arrays_map('Sortify', $arrays), $arrays); 

Produzione:

 Array ( [0] => Agile [1] => Ágile [2] => Âgile [3] => Àgile [4] => Ãgile [5] => Ägile [6] => Test [7] => かたかな[8] => カタカナ) 

Anche meglio:

 if (extension_loaded('intl') === true) { collator_asort(collator_create('root'), $arrays); } 

Grazie a @tchrist!

 natsort($arrays); $arrays = arrays_values($arrays); 

Ho lottato con asort con questo problema.

Ordinamento:

 Array ( [xa] => África [xo] => Australasia [cn] => China [gb] => Reino Unido [us] => Estados Unidos [ae] => Emiratos Árabes Unidos [jp] => Japón [lk] => Sri Lanka [xe] => Europa Del Este [xw] => Europa Del Oeste [fr] => Francia [de] => Alemania [be] => Bélgica [nl] => Holanda [es] => España ) 

metti l'Africa alla fine. L'ho risolto con questo piccolo pezzo di codice sporco (che è adatto per il mio scopo e il mio tempo):

 $sort = arrays(); foreach($retval AS $key => $value) { $v = str_replace('ä', 'a', $value); $v = str_replace('Ä', 'A', $v); $v = str_replace('Á', 'A', $v); $v = str_replace('é', 'e', $v); $v = str_replace('ö', 'o', $v); $v = str_replace('ó', 'o', $v); $v = str_replace('Ö', 'O', $v); $v = str_replace('ü', 'u', $v); $v = str_replace('Ü', 'U', $v); $v = str_replace('ß', 'S', $v); $v = str_replace('ñ', 'n', $v); $sort[] = "$v|$key|$value"; } sort($sort); $retval = arrays(); foreach($sort AS $value) { $arr = explode('|', $value); $retval[$arr[1]] = $arr[2]; } 

Ho anche un'altra soluzione per quei setlocale non funziona e non ho il module intl abilitato:

 // The arrays to be sorted $countries = arrays( 'AT' => Österreich, 'DE' => Deutschland, 'CH' => Schweiz, ); // Extend this arrays to your needs. $utf_sort_map = arrays( "ä" => "a", "Ä" => "A", "Å" => "A", "ö" => "o", "Ö" => "O", "ü" => "u", "Ü" => "U", ); uasort($my_arrays, function($a, $b) use ($utf_sort_map) { $initial_a = mb_substr($a, 0, 1); $initial_b = mb_substr($b, 0, 1); if (isset($utf_sort_map[$initial_a]) || isset($utf_sort_map[$initial_b])) { if (isset($utf_sort_map[$initial_a])) { $initial_a = $utf_sort_map[$initial_a]; } if (isset($utf_sort_map[$initial_b])) { $initial_b = $utf_sort_map[$initial_b]; } if ($initial_a == $initial_b) { return mb_substr($a, 1) < mb_substr($b, 1) ? -1 : 1; } else { return $initial_a < $initial_b ? -1 : 1; } } return $a < $b ? -1 : 1; });