skip to Main Content

I’m trying to sort my array values by size but I have a problem.
My array pulls out values that are different than the values of the "cmp" function used to sort.
The code is this:

function cmp($a, $b)
{

    $sizes = array(
        "XXS" => 0,
        "XS" => 1,
        "S" => 2,
        "M" => 3,
        "L" => 4,
        "XL" => 5,
        "XXL" => 6,
    );

    $asize = $sizes[$a];
    $bsize = $sizes[$b];

    if ($asize == $bsize) {
        return 0;
    }

    return ($asize > $bsize) ? 1 : -1;
}

$your_array = array("GL001_XXL", "GL001_L", "GL001_XXS", "GL001_S");

usort($your_array, "cmp");

When I try to print this value it tells me "Undefined key".
How can I sort my array without errors?

2

Answers


  1. As noted in the comments, if your pattern is truly xxx_size, you can just explode on the _ and grab the second item.

    The <=> can be used whenever you’ve got the "return 0, 1 or -1" pattern, too.

    function sort_array_item_by_size($a, $b): int
    {
        static $sizes = [
            "XXS" => 0,
            "XS" => 1,
            "S" => 2,
            "M" => 3,
            "L" => 4,
            "XL" => 5,
            "XXL" => 6,
        ];
    
        // The next three lines really should include some error checking
        $size_a = explode("_", $a)[1];
        $size_b = explode("_", $b)[1];
    
        return $sizes[$size_a] <=> $sizes[$size_b];
    }
    
    $your_array = ["GL001_XXL", "GL001_L", "GL001_XXS", "GL001_S"];
    
    usort($your_array, "sort_array_item_by_size");
    
    print_r($your_array);
    
    // Array
    // (
    //     [0] => GL001_XXS
    //     [1] => GL001_S
    //     [2] => GL001_L
    //     [3] => GL001_XXL
    // )
    

    Demo: https://3v4l.org/Dqfi6

    Login or Signup to reply.
  2. I advise against using usort() for this task because this involves parsing both strings each iteration (which is more than N times).

    Instead, it will be more performant and very concise to use array_multisort(). Because your input strings appear to be consistently padded with zeros, you can simply parse the strings by grabbing the substring starting from the 6th character offset.

    Code: (Demo)

    define('SIZES', array_flip(['XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL']));
    
    $array = ["GL001_XXL", "GL001_L", "GL001_XXS", "GL001_S"];
    
    array_multisort(
        array_map(fn($v) => SIZES[substr($v, 6)], $array),
        $array
    );
    var_export($array);
    

    This approach will have the bonus effect of breaking ties (identical size values) by performing natural comparisons on the whole strings.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search