2017-01-11 1 views
0

J'essaie de trier un tableau par un alphabet personnalisé (noms internationaux, aucune des locales de Collator ne les place exactement dans l'ordre que je veux).Collation personnalisée avec php en utilisant usort

J'ai volé du code de here et ai.

function compare_by_alphabet($str1, $str2){ 
    $alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ"; 
    $l1 = strlen($str1); 
    $l2 = strlen($str2); 
    $c = min($l1, $l2); 

    for ($i = 0; $i < $c; $i++) 
    { 
     $s1 = substr($str1, $i, 1); 
     $s2 = substr($str2, $i, 1); 
     if ($s1===$s2) continue; 
     $i1 = strpos($alphabet, $s1); 
     if ($i1===false) continue; 
     $i2 = strpos($alphabet, $s2); 
     if ($i2===false) continue; 
     if ($i2===$i1) continue; 
     if ($i1 < $i2) return -1; 
     else return 1; 
    } 
    if ($l1 < $l2) return -1; 
    elseif ($l1 > $l2) return 1; 
    return 0; 
} 

Lorsque je tente

$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"]; 
usort($names, 'compare_by_alphabet'); 

Je reçois ["Asber","Ås","Åsberg","Schön","Schon","Žižek","Zierer"] - sont mauvais de deux Schon était là, tout comme Žižek et Zierer.

Il me manque quelque chose ici. Quelqu'un peut-il expliquer pourquoi cela ne se comporte pas comme prévu, s'il vous plaît? Ou comment je peux le réparer?

Répondre

0

Les fonctions de chaînes PHP standard ne sont pas compatibles multi-octets. Dans votre exemple, les chaînes et l'alphabet contiennent des caractères multi-octets (la plupart des éditeurs php modernes utiliseront utf-8 par défaut encoding). Par exemple, À est en réalité représenté par 2 octets dans utf-8.

Exécutez la commande suivante pour vérifier que:

php > echo strlen("À"); 
2 

Utilisez multibyte string fonctions pour résoudre le problème.

Après avoir appliqué ce, le code est:

function compare_by_alphabet($str1, $str2) { 

    $alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ"; 
    $l1 = mb_strlen($str1); 
    $l2 = mb_strlen($str2); 
    $c = min($l1, $l2); 

    for ($i = 0; $i < $c; $i++) 
    { 
     $s1 = mb_substr($str1, $i, 1); 
     $s2 = mb_substr($str2, $i, 1); 
     if ($s1===$s2) continue; 
     $i1 = mb_strpos($alphabet, $s1); 
     if ($i1===false) continue; 
     $i2 = mb_strpos($alphabet, $s2); 
     if ($i2===false) continue; 


    if ($i2===$i1) continue; 
     if ($i1 < $i2) return -1; 
     else return 1; 
    } 
    if ($l1 < $l2) return -1; 
    elseif ($l1 > $l2) return 1; 
    return 0; 
} 

$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"]; 
usort($names, 'compare_by_alphabet'); 
var_dump($names); 

et le résultat

array(7) { 
    [0]=>string(5) "Asber" 
    [1]=>string(3) "Ås" 
    [2]=>string(7) "Åsberg" 
    [3]=>string(5) "Schon" 
    [4]=>string(6) "Schön" 
    [5]=>string(6) "Zierer" 
    [6]=>string(7) "Žižek" 
} 
+0

Je ne savais pas! Merci beaucoup, appréciez-le. – Richie