Haim Evgi
Haim Evgi

Reputation: 125674

Sort a flat array of strings case-insensitively then case-sensitively

I want to sort an array alphabetically.

When I use asort(), it's sorting, but the results position the strings starting with uppercase first then the strings starting with lowercase.

Avi
Beni
..
..
avi
beni

I want the sorting to be:

Avi
avi
Beni
beni
..
..

How can I do it?

Upvotes: 0

Views: 549

Answers (4)

mickmackusa
mickmackusa

Reputation: 48100

Your sample data doesn't have any numbers in it so it doesn't make sense to perform "natural" sorting.

You can rely on a stable sort and just sort case-insensitively after sorting case-sensitively. PHP guarantees a stable sort as of PHP8. Depending on your data, you might get the right results earlier -- but don't bet on it. Demo

$array = ['avi', 'beni', 'Avi', 'Beni'];

sort($array);
sort($array, SORT_STRING | SORT_FLAG_CASE);

var_export($array);

Without relying on a stable sort (right down to PHP5.4 when SORT_FLAG_CASE was added), sort case-insensitively then break ties with a case-sensitive sort. Demo

$array = array('avi', 'beni', 'Avi', 'Beni');

array_multisort(
    $array,
    SORT_STRING | SORT_FLAG_CASE,
    $array
);

var_export($array);

Rounding out this answer with a usort() call, compare insensitivity and break ties by comparing sensitively. Demo

$array = ['avi', 'beni', 'Avi', 'Beni'];

usort(
    $array,
    fn($a, $b) => strcasecmp($a, $b) ?: strcmp($a, $b)
);

var_export($array);

Output from all of above:

array (
  0 => 'Avi',
  1 => 'avi',
  2 => 'Beni',
  3 => 'beni',
)

Upvotes: 0

Eineki
Eineki

Reputation: 14959

The proposed solutions, until now, arent correct, natcasesort and the usort($arr, 'strcasecmp') solutions are failing with some starting array configurations.

Let do some tests, to find a solution.

<?php
$array1 = $array2 = $array3 = $array4 = $array5 = array('IMG1.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG2.png');

// This result is the one we nee to avoid
sort($array1);
echo "Standard sorting\n";
print_r($array1);

// img2.png and IMG2.png are not in the desired order
// note also the array index order in the result array
natcasesort($array2);
echo "\nNatural order sorting (case-insensitive)\n";
print_r($array2);

// img1.png and IMG1.png are not in the desired order
usort($array3, 'strcasecmp');
echo "\nNatural order sorting (usort-strcasecmp)\n";
print_r($array3);

// Required function using the standard sort algorithm
function mySort($a,$b) {
  if (strtolower($a)== strtolower($b))
    return strcmp($a,$b);
  return strcasecmp($a,$b);
}

usort($array4, 'mySort');
echo "\nStandard order sorting (usort-userdefined)\n";
print_r($array4);

// Required function using the natural sort algorithm
function myNatSort($a,$b) {
  if (strtolower($a)== strtolower($b))
    return strnatcmp($a,$b);
  return strnatcasecmp($a,$b);
}

usort($array5, 'myNatSort');
echo "\nNatural order sorting (usort-userdefined)\n";
print_r($array5);

?>

Upvotes: 2

shamittomar
shamittomar

Reputation: 46712

You can use netcasesort(). It sort an array using a case insensitive "natural order" algorithm.

Do it like this:

natcasesort($array);

Upvotes: 4

Sjoerd
Sjoerd

Reputation: 75699

natcasesort

Upvotes: 2

Related Questions