Основанная на локали сортировка массивов в PHP дает другой результат на OS X, чем Ubuntu - PullRequest
0 голосов
/ 08 мая 2019

Учитывая следующий массив:

$foo = ["a", "B", "æ", "Æ", "c", "A", "b", "C", "1"];

Затем я устанавливаю локаль с помощью setlocale(LC_ALL, ['nb_NO.UTF-8', 'no_NO.UTF-8']); и запускаю массив через sort($foo, SORT_LOCALE_STRING).

В Ubuntu отсортированный массив будет выглядеть так:

[
  0 => '1',
  1 => 'A',
  2 => 'a',
  3 => 'B',
  4 => 'b',
  5 => 'C',
  6 => 'c',
  7 => 'Æ',
  8 => 'æ',
]

В то время как на Mac (OS X) я получаю:

[
  0 => '1',
  1 => 'A',
  2 => 'B',
  3 => 'C',
  4 => 'a',
  5 => 'b',
  6 => 'c',
  7 => 'Æ',
  8 => 'æ',
]

Кажется, OS X хочет отсортировать строки, начинающиеся с заглавных букв, по отдельности (ABC, затем abc), в то время как я просто хотел бы, чтобы они были вместе (AaBbCc).

Есть ли способ заставить их сортировать массивы таким же образом в PHP, или мне нужно написать собственный метод сортировки, используя вместо этого один из методов u*sort()?

Редактировать: похоже, очень похоже на вопрос, который помечен как дубликат . Хотя OS X все еще, кажется, сортирует прописные и строчные буквы друг за другом вместо того, чтобы смешивать их, это можно исправить, добавив strtolower() к функции сортировки.

1 Ответ

1 голос
/ 11 мая 2019

Самый чистый, самый профессиональный способ решить эту проблему - убедиться, что вы на самом деле устанавливаете одинаковый языковой стандарт в обеих средах.Пожалуйста, прочитайте руководство и комментарии, представленные ниже спецификации , чтобы узнать, как правильно установить и получить локаль.Установка локали может быть сложным делом, вам может потребоваться изменить синтаксис для одних и объявить запасные значения для других.Твой труд.

Что касается горячего / временного исправления, вы можете вызвать usort() с оператором космического корабля, помещенным между массивом условий.Во-первых, сравните $a против $b после многобайтового безопасного преобразования их обоих в верхний регистр, если это сравнение является связью, то оператор космического корабля сделает сравнение с необработанными $a против $b.

Код: ( Демо )

$foo = ["a", "B", "æ", "Æ", "c", "A", "b", "C", "1"];

usort($foo, function($a, $b) {
    return [mb_strtoupper($a), $a] <=> [mb_strtoupper($b), $b];
});

var_export($foo);

Выход:

array (
  0 => '1',
  1 => 'A',
  2 => 'a',
  3 => 'B',
  4 => 'b',
  5 => 'C',
  6 => 'c',
  7 => 'Æ',
  8 => 'æ',
)
...