2017-01-11 2 views
0

Я пытаюсь сортировать массив по произвольному алфавиту (международные имена, ни одна из локаций Collator не помещает их точно в том порядке, который я хочу).Пользовательская сортировка с использованием php с использованием usort

Я украл код от here и у вас есть.

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

Когда я пытаюсь

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

["Asber","Ås","Åsberg","Schön","Schon","Žižek","Zierer"] я - два Schon является неправильно было вокруг, как и Жижки и Zierer.

Мне что-то не хватает. Может кто-нибудь объяснить, почему это не ведет себя так, как ожидалось, пожалуйста? Или как я могу это исправить?

ответ

0

Стандартные функции строки PHP не совместимы с многобайтовыми. В вашем примере строки и алфавит, однако, содержат многобайтовые символы (большинство современных редакторов php будут использовать utf-8 по умолчанию encoding). Например, À фактически представляется 2 байтами в utf-8.

Выполните следующие действия, чтобы проверить, что:

php > echo strlen("À"); 
2 

Использование multibyte string функции для решения этой проблемы.

После применения этого кода:

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

и результат

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

Я не знал, что! Большое спасибо, оцените это. – Richie

Смежные вопросы