I am trying to sort my array values with sizes but the result is not as I expected.
This is my code:
function cmp($a, $b) {
$sizes = array(
"XS" => 0,
"S" => 1,
"M" => 2,
"L" => 3,
);
$size_a = explode("_", $a)[1];
$size_b = explode("_", $b)[1];
return $sizes[$size_a] <=> $sizes[$size_b];
}
$array = array("GL001_M","GL001_XS","GL001_S",
"GL001_L","GL002_M","GL002_XS",
"GL002_S","GL002_L");
usort($array,"cmp");
foreach($array as $arrayItem){
echo $arrayItem.' | ';
}
My output is this:
GL001_XS | GL002_XS | GL001_S | GL002_S | GL001_M | GL002_M | GL001_L | GL002_L |
Instead I would like this:
GL001_XS | GL001_S | GL001_M | GL001_L | GL002_XS | GL002_S | GL002_M | GL002_L |
2
Answers
The issue with the current method is that it only sorts on the final part of each string (so the ‘S’, ‘XS’ etc.)
What you can do is expand the comparison to sort on the first part (‘GL001’) and only when there is a match to use the size to sort them.
So
$size_a[0] <=> $size_b[0]
will compare the ‘GL001’ bits.The using
?:
it will return the second part if the value of the first part is 0 (i.e. they are the same).$sizes[$size_a[1]]
will be the size translated by the array (so ‘S’ => 1).Wow, this question is super similar to Custom sort on value suffix representing sizes (XXS, XS, S, M, L, XL, XXL), but the fact that you are sorting by both halves of the input strings AND the desired size values can be sorted alphabetically, my advice will change. No lookup array is necessary. Calling
explode()
with linear time complexity will mean fewerexplode()
calls than 2 perusort()
iteration.Code: (Demo)
Once you have to accommodate sizes greater than
L
, then a lookup array is needed.Code: (Demo)
And if you are super disgruntled with the other developers that you work with, you give them sore eyes with this fully functional-style snippet with no new, globally scoped variables! Demo