Skip to content
Advertisement

Array sort by key where keys are clothes sizes (S, M, L, etc.)

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);
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement