игнорировать символы с диакритическими знаками при сортировке по php в многомерном массиве - PullRequest
3 голосов
/ 07 августа 2020

У меня есть многомерный массив, как показано ниже, в котором я хочу выполнить сортировку на основе поля [name]. Кроме того, буквы с диакритическими знаками следует сортировать так, как если бы они не были акцентированы.

Array
(
    [chicago] => Array
        (
            [community_name] => Chicago, IL
            [areas] => Array
                (
                    [0] => Array
                        (
                            [name] => Array
                                (
                                    [0] => HELLO WORLD.
                                )
                        )

                    [1] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Hello
                                )

                        )

                    [2] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Administration.
                                )
                        )
                )

        )

    [chicago-and-surrounding-areas] => Array
        (
            [community_name] => Chicago (and surrounding areas), IL
            [areas] => Array
                (
                    [0] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Covit Corp. 
                                )
                        )
                    [1] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Câble-Axion Digital Corp. 
                                )
                        )   
                )

        )

    [cambridge-chicago] => Array
        (
            [community_name] => Cambridge (Chicago), IL
            [areas] => Array
                (
                    [0] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Avocados.
                                )
                        )
                    [1] => Array
                        (
                            [name] => Array
                                (
                                    [0] => Aṕple.
                                )
                        )   
                )

        )

)

Это то, чего я хочу достичь: будет работать во всех случаях. В некоторых случаях даже после сортировки букв с диакритическими знаками ранг ниже, чем у их аналогов без акцента.

foreach ($array as &$locality) {
    usort($locality['areas'], function ($a, $b) {
        // return $a['name'][0] <=> $b['name'][0];
        return iconv('UTF-8', 'ISO-8859-8//TRANSLIT', $a['name'][0]) <=> iconv('UTF-8', 'ISO-8859-8//TRANSLIT', $b['name'][0]);
    });
}

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Использовать intl's Collator:

$arr = [
  ['key' => 'Avocado'],
  ['key' => 'Aṕple'],
];

$c = new Collator('root');
usort(
    $arr,
    function($a, $b) use($c){
        return $c->compare($a['key'], $b['key']);
    }
);
var_dump($arr);

Вывод:

array(2) {
  [0]=>
  array(1) {
    ["key"]=>
    string(7) "Aṕple"
  }
  [1]=>
  array(1) {
    ["key"]=>
    string(7) "Avocado"
  }
}

Где 'root' использует набор правил по умолчанию, которые, по-видимому, игнорируют акценты по желанию, хотя вы можете указать фактические языковые стандарты для языков c порядок сортировки.

1 голос
/ 07 августа 2020

Вы можете использовать Нормализатор , чтобы отделить символы от диакритических знаков и удалить их после, чтобы получить «базовые» символы.

function stripDiacritics(string $string): string {
    return preg_replace(
        '/[\x{0300}-\x{036f}]/u',
        '',
        Normalizer::normalize($string , Normalizer::FORM_D)
    );
}

foreach ($array as &$locality) {
    usort($locality['areas'], function ($a, $b) {
        return stripDiacritics($a['name'][0]) <=> stripDiacritics($b['name'][0]);
    });
}    

Рабочий пример .

Удалите из здесь .

В следующий раз используйте var_export , чтобы мы могли использовать ваш массив для проверки кода :)

Список диакритических знаков (источник \x{0300}-\x{036f}).

...