2

How to use multiple sort_flags in PHP array sorting (Using SORT_LOCALE_STRING , SORT_NATURAL)?

I want to using SORT_LOCALE_STRING for UTF8 languages + SORT_NATURAL Numbers.


I want to Sort the following array:

$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');

My favorite result after sorting:

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha2
    [3] => Älpha3
    [4] => Älpha4
    [5] => Älpha10
    [6] => Bravo
)

But when using SORT_LOCALE_STRING:

<?php
$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');
setlocale(LC_COLLATE, 'de_DE.UTF8', 'de.UTF8', 'de_DE.UTF-8', 'de.UTF-8');
sort($array, SORT_LOCALE_STRING);
print_r($array);
?>

Results:

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha10
    [3] => Älpha2
    [4] => Älpha3
    [5] => Älpha4
    [6] => Bravo
)

AND when using SORT_NATURAL:

<?php
$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');
sort($array, SORT_NATURAL);
print_r($array);
?>

Results:

Array
(
    [0] => Alpha
    [1] => Bravo
    [2] => Älpha1
    [3] => Älpha2
    [4] => Älpha3
    [5] => Älpha4
    [6] => Älpha10
)

How can I get result like this?!

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha2
    [3] => Älpha3
    [4] => Älpha4
    [5] => Älpha10
    [6] => Bravo
)

UPDATE:

I finally found the solution, By Using intl AND The Collator class.

First, enable PHP Extension intl.

Then:

<?php
$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');
$collator = new Collator('de_DE.UTF8');
$collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
$collator->setAttribute(Collator::CASE_FIRST, Collator::LOWER_FIRST);
$collator->asort($array);
print_r($array);
?>

Results:

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha2
    [4] => Älpha3
    [5] => Älpha4
    [3] => Älpha10
    [6] => Bravo
)

2 Answers 2

1

The issue is that the two flags you want to use almost contradict each other. SORT_NATURAL wants to treat the value as a mixture of a string and numeric, whereas SORT_LOCALE_STRING wants to treat it purely as a string.

Not sure if there is a simpler way, but this code translates all the letters into a standard alphabet (using iconv()), sorts this array (using asort to keep the keys and SORT_NATURAL) and then substitutes back the original string (using array_replace())...

$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');
setlocale(LC_ALL, "en_US.utf8");
$trans = $array;
array_walk($trans, function (&$data) {
    $data =  iconv("UTF-8", 'ASCII//TRANSLIT//IGNORE', $data);
});
asort($trans, SORT_NATURAL);
$array = array_replace($trans, $array);
print_r($array);

gives...

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha2
    [4] => Älpha3
    [5] => Älpha4
    [3] => Älpha10
    [6] => Bravo
)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply. But your solution is not working properly in some languages, such as Arabic. Please see the solution in the First post.
It's difficult to know all of the classes or possibilities, but at least you found what you are after. I would suggest posting that as an answer, and you can (eventually) choose it as the accepted answer.
1

First, enable PHP Extension intl.

Then:

<?php
$array=array('Alpha', 'Älpha1', 'Älpha2', 'Älpha10', 'Älpha3', 'Älpha4', 'Bravo');
$collator = new Collator('de_DE.UTF8');
$collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
$collator->setAttribute(Collator::CASE_FIRST, Collator::LOWER_FIRST);
$collator->asort($array);
print_r($array);
?>

Results:

Array
(
    [0] => Alpha
    [1] => Älpha1
    [2] => Älpha2
    [4] => Älpha3
    [5] => Älpha4
    [3] => Älpha10
    [6] => Bravo
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.