Intereting Posts

Как я могу отсортировать массив строк UTF-8 в PHP?

нужна помощь в сортировке слов utf-8. Например, у нас есть 5 городов из Бельгии.

$array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); sort($array); // Expected: Aubel, Borgloon, Éghezée, Lennik, Thuin // Actual: Aubel, Borgloon, Lennik, Thuin, Éghezée 

Город Эгезе должен быть третьим. Можно ли использовать / установить какой-то utf-8 или создать собственный порядок символов?

intl поставляется в комплекте с PHP из PHP 5.3 и поддерживает только UTF-8 .

Вы можете использовать Collator в этом случае:

 $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); $collator = new Collator('en_US'); $collator->sort($array); print_r($array); 

Вывод:

 Array ( [0] => Aubel [1] => Borgloon [2] => Éghezée [3] => Lennik [4] => Thuin ) 

Я думаю, вы можете использовать strcoll :

 setlocale(LC_COLLATE, 'nl_BE.utf8'); $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); usort($array, 'strcoll'); print_r($array); 

Результат:

 Array ( [0] => Aubel [1] => Borgloon [2] => Éghezée [3] => Lennik [4] => Thuin ) 

Вам нужна локаль nl_BE.utf8 в вашей системе:

 fy@Heisenberg:~$ locale -a | grep nl_BE.utf8 nl_BE.utf8 

Если вы используете debian, вы можете использовать dpkg -reconfigure locales для добавления локалей.

Этот скрипт должен быть выполнен по-своему. Надеюсь, это поможет. Обратите внимание на функцию mb_strtolower. Вы должны использовать его, чтобы сделать регистр функции нечувствительным. Причина, по которой я не использовал функцию strtolower, заключается в том, что она не работает с особыми символами.

 <?php function customSort($a, $b) { static $charOrder = array('a', 'b', 'c', 'd', 'e', 'é', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); $a = mb_strtolower($a); $b = mb_strtolower($b); for($i=0;$i<mb_strlen($a) && $i<mb_strlen($b);$i++) { $chA = mb_substr($a, $i, 1); $chB = mb_substr($b, $i, 1); $valA = array_search($chA, $charOrder); $valB = array_search($chB, $charOrder); if($valA == $valB) continue; if($valA > $valB) return 1; return -1; } if(mb_strlen($a) == mb_strlen($b)) return 0; if(mb_strlen($a) > mb_strlen($b)) return -1; return 1; } $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); usort($array, 'customSort'); 

EDIT: Извините. Я совершил много ошибок в последнем коде. Теперь тестируется.

EDIT {2}: все с многобайтовыми функциями.

У меня возникло бы желание перебирать массив и преобразовывать его в английские символы перед сортировкой. Например

 <?php $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); setlocale(LC_CTYPE, 'nl_BE.utf8'); $newarray = array(); foreach($array as $k => $v) { $newarray[$k] = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $v); } sort($newarray); print_r($newarray); ?> 

Вероятно, это не самая лучшая с точки зрения скорости обработки / используемых ресурсов. Но уверен, что это облегчает понимание кода.

Редактировать:

Думая об этом сейчас, вам может быть лучше использовать какую-то таблицу поиска, что-то вроде этого:

 <?php $accentedCharacters = array ( 'à', 'á', 'â', 'ã', 'ä', 'å', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Š', 'Ž', 'š', 'ž', 'Ÿ', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý' ); $replacementCharacters = array ( 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'S', 'Z', 's', 'z', 'Y', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y' ); $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); $newarray = array(); foreach($array as $k => $v) { $newarray[$k] = str_replace($accentedCharacters,$replacementCharacters,$v); } sort($newarray); print_r($newarray); ?> 

Что касается strcoll, я думаю, это была хорошая идея, но, похоже, не работает:

 <?php // Some $strings = array('Alpha', 'Älpha', 'Bravo'); // make it German: A, Ä, B setlocale(LC_COLLATE, 'de_DE.UTF8', 'de.UTF8', 'de_DE.UTF-8', 'de.UTF-8'); usort($strings, 'strcoll'); var_dump($strings); // as you can see, Ä is last, so this didn't work 

Некоторое время назад я написал инструмент UTF-8 для ASCII , который преобразует «älph # bla» в «aelph-bla». Вы можете использовать это для «нормализации» вашего ввода, чтобы сделать его сортируемым. Это в основном замена, похожая на то, что сказал @Nick.

Вы должны использовать отдельный массив для сортировки, поскольку вызов urlify () в обратном вызове usort () будет тратить массу ресурсов. пытаться

 <?php // data to sort $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel'); // container for modified strings $_array = array(); foreach ($array as $k => $v) { // "normalize" utf8 to ascii $_array[$k] = urlify($v); } // sort the ASCII stuff (while preserving indexes) asort($_array); foreach ($_array as $key => &$v) { // copy the original value of the ASCIIfied element $v = $array[$k]; } var_dump($_array); 

Если у вас есть PHP5.3 или встроенный PECL скомпилированный, попробуйте @ тайский решение, кажется сладким!

Если вы хотите использовать собственное решение, поэтому я могу предложить этот

 function compare($a, $b) { $alphabet = 'aąbcćdeęfghijklłmnnoóqprstuvwxyzźż'; // i used polish letters $a = mb_strtolower($a); $b = mb_strtolower($b); for ($i = 0; $i < mb_strlen($a); $i++) { if (mb_substr($a, $i, 1) == mb_substr($b, $i, 1)) { continue; } if ($i > mb_strlen($b)) { return 1; } if (mb_strpos($alphabet, mb_substr($a, $i, 1)) > mb_strpos($alphabet, mb_substr($b, $i, 1))) { return 1; } else { return -1; } } } usort($needed_array, 'compare'); 

Не уверен, это лучшее решение, но оно работает для меня =)