Search code examples
phparrayssortingmultidimensional-arraycustom-sort

Sort rows of a 2d array by a column ascending, but with all false values at the end


I have a multidimensional array that I'd like to sort based on the distance value where the false values should be added to the end in their former positions regarding their arrays.

$array = array(
        array('name' => 'Array 1', 'distance' => 3.4),
        array('name' => 'Array 2', 'distance' => 2.4),
        array('name' => 'Array 3', 'distance' => false),
        array('name' => 'Array 4', 'distance' => 5.4),
        array('name' => 'Array 5', 'distance' => false),
        array('name' => 'Array 6', 'distance' => 1),
        array('name' => 'Array 7', 'distance' => false),
        array('name' => 'Array 8', 'distance' => false),
        array('name' => 'Array 9', 'distance' => 3.6),
    );

I'd like to sort it to this:

Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 3 
Array 5 
Array 7 
Array 8 

I can only get it to this:

Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 8 
Array 5 
Array 3 
Array 7 

My attempt:

usort($array, function($a, $b){
    if(!$b['distance'])
        return -1;
    elseif(!$a['distance'])
        return 1;

    return $a['distance'] - $b['distance'];
});

EDIT: added my solution as an answer


Solution

  • $withDistance = array();
    $withoutDistance = array_filter($array, function($array) use (&$withDistance) {
        if($array['distance'] !== false) {
            $withDistance[] = $array;
            return false;
        }
        return true;
    });
    
    usort($withDistance, function($a, $b){
        if ($a['distance'] == $b['distance']) return 1;
        return $a['distance'] > $b['distance'] ? 1: -1;
    });
    
    $array = array_merge($withDistance, $withoutDistance);