Sorting Russian/English list

2.3k Views Asked by At

I have the following array which has both English and Russian words in it:

[0]  => Airline_1
[1]  => Second Air
[2]  => Авиатор
[3]  => Аврора

I'm using the following function to sort it:

    uasort($newCompanyList, function ($a, $b) {
        $at = iconv('UTF-8', 'ASCII//TRANSLIT', $a);
        $bt = iconv('UTF-8', 'ASCII//TRANSLIT', $b);
        return strcmp($at, $bt);
    });

The expected result is this:

[0]  => Airline_1
[2]  => Авиатор
[3]  => Аврора
[1]  => Second Air

The problem is that it does sort the list, but it sorts them seperatelly, I need russian 'A' to be next to english 'A' if that makes sense. How may I achieve that?

2

There are 2 best solutions below

0
On BEST ANSWER

You may try making an aggregated array of characters like:

$customAlfabet = array(
    'A', // EN
    'А', // RU
    'B', // EN
    'Б', // RU
    ...
);

Then apply the sorting based on the numeric key of the array.

uasort($newCompanyList, function ($a, $b) {
    if ($a[0] > $b[0]) {
        return 1;
    } elseif ($a[0] < $b[0]) {
        return -1;
    }
    return 0;
});

It's better to apply recursion here, that if the first character is the same - check the second character, third, etc.

NOTE, that for example character З which has the equivalent sounding of Z, is positioned as the 9nth character in Russian alfabet, while Z being the last one in English, so it's best not to do that from UX point of view.

3
On

You may use Intl extension and Transliterator object, like so:

$transliterator = Transliterator::create('Any-Latin; Latin-ASCII;');
uasort($newCompanyList, function ($a, $b) use ($transliterator) {
    $at = $transliterator->transliterate($a);
    $bt = $transliterator->transliterate($b);
    return strcmp($at.$a, $bt.$b);
});

I've appended original strings to final comparison to differentiate cases where transliteration of russian string and latin one produce the same transliteration.