I have an array where it’s keys are the sizes and values are either 'in-stock'
or 'no-stock'
.
Example array:
$data = [ 'L' => 'in-stock', 'S' => 'in-stock', 'XL' => 'no-stock', 'M' => 'in-stock', ];
I’m trying to sort this by size. Expected output is:
$data = [ 'S' => 'in-stock', 'M' => 'in-stock', 'L' => 'in-stock', 'XL' => 'no-stock', ];
I’ve been looking at other similar questions but with no success because those had different array structures.
I’m struggling with the uksort
function since what I want is to sort the array and preserve the keys.
uksort($data, function($a, $b) use ($data) { static $sizes; // filter out only used size values => ['S', 'M', 'L', 'XL'] $sizes = array_filter(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"], function($arr) use ($data) { return array_key_exists($arr, $data); }); $sizes = array_values($sizes); if (array_search($a, $sizes) === array_search($b, array_keys($data))) { return 0; } if (array_search($a, $sizes) < array_search($b, array_keys($data))) { return -1; } if (array_search($a, $sizes) > array_search($b, array_keys($data))) { return 1; } });
Result:
Array ( [S] => in-stock [L] => in-stock [XL] => in-stock [M] => in-stock )
Im trying to compare key positions in $data
and defined sort order in $sizes
. It does not work and i’m struggling to fully understand how to properly compare $a
and $b
in the uksort
callback.
https://www.php.net/manual/en/function.uksort.php
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
Advertisement
Answer
If you have a definite order, don’t use it for sorting, but rather for mapping. E.g.:
$data = [ 'L' => 'in-stock', 'S' => 'in-stock', 'XL' => 'no-stock', 'M' => 'in-stock', ]; function getOrderedBySize(array $data): array { $result = []; foreach (["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"] as $key) { if (array_key_exists($key, $data)) { $result[$key] = $data[$key]; } } return $result; } print_r($data); print_r(getOrderedBySize($data));
Though if you absolutely wanted to sort the input array, this will do:
$fixedOrder = array_flip(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"]); uksort($data, static fn(string $a, string $b): int => $fixedOrder[$a] <=> $fixedOrder[$b]); print_r($data);