phparrayssortingassociative-arraycustom-sort

Custom sorting a flat array with uasort() returns 1


An array arrives with some or all of the following values, in any order. What's the best way to order them in ascending size order? So starting with small and ending with XXL. I can usort but am a bit lost as to how the elements should be ordered in my user defined function

Small
XXL
Medium
Large 
XL

EDIT: left out some info so created new question Custom ordering array with key / value pairs

EDIT2: Full code

print_r($sizes);
$sorted_sizes = $this->sort_sizes(array_unique($sizes));
print_r($sorted_sizes);

function sort_sizes($sizes)
{
    return uasort($sizes, array($this, 'cmp'));
}

function cmp($a,$b)
{
    $sizeArray = array( 'Small' => 0, 'Medium' => 1, 'Large' => 2, 'XL' => 3, 'XXL' => 4); 
    return $sizeArray[$a] - $sizeArray[$b];
}

This outputs:

Array
(
    [66-507cddcd16d9786abafccfa78b19acf8] => XL
    [64-507cddcd16d9786abafccfa78b19acf8] => medium
    [65-507cddcd16d9786abafccfa78b19acf8] => large
    [63-507cddcd16d9786abafccfa78b19acf8] => small
)

and print_r($sorted_sizes) just gives output "1"


Solution

  • Updated answer according to full code

    The first issue here is that you're returning the result of uasort():

    function sort_sizes($sizes)
    {
        return uasort($sizes, array($this, 'cmp'));
    }
    

    That's wrong, because uasort() does not return the sorted array. It modifies the same variable that you pass as a parameter, and returns a boolean value. That's why you see 1 as output.

    Make the method accept $sizes by reference:

    function sort_sizes(array &$sizes)
    {
        uasort($sizes, array($this, 'cmp'));
    }
    

    Then call it like so:

    print_r($sizes);
    $sorted_sizes = array_unique($sizes);
    $this->sort_sizes($sorted_sizes);
    print_r($sorted_sizes);
    

    Here's your cmp() method, with added support for case-insensitive sorting:

    function cmp($a, $b)
    {
        $sizes = array('small' => 0, 'medium' => 1, 'large' => 2, 'xl' => 3, 'xxl' => 4);
        return $sizes[strtolower($a)] - $sizes[strtolower($b)];
    }
    

    Old answer

    Try this. Use uasort() instead if you want to maintain key-value pairs:

    function sort_sizes($a, $b) {
        // Map the sizes to an ordered sequence of ints
        static $sizes = array('small' => 0, 'medium' => 1, 'large' => 2, 'xl' => 3, 'xxl' => 4);
    
        // Find the difference, using the sizes as keys to the above array
        return $sizes[strtolower($a)] - $sizes[strtolower($b)];
    }
    
    $arr = array('Small', 'XXL', 'Medium', 'Large', 'XL');
    
    print_r($arr); // Before sorting
    uasort($arr, 'sort_sizes');
    print_r($arr); // After sorting
    

    Output:

    Array
    (
        [0] => Small
        [1] => XXL
        [2] => Medium
        [3] => Large
        [4] => XL
    )
    Array
    (
        [0] => Small
        [2] => Medium
        [3] => Large
        [4] => XL
        [1] => XXL
    )