Search code examples
phparrayssortingmultidimensional-arrayarray-multisort

Sort all rows of a 2d array according to one row and maintain columnar relationships


I have an array with mostly unknown first level keys. I would like to sort all of the rows in a synchronous way so that when sortBy is sorted ascendingly, all other rows will have their data positioned to maintain columnar relationships.

[
    'sortBy' => [3, 2, 1],
    'other'  => ['x', 'y', 'z'],
    'xxx'    => [3, 2, 1],
    'foo'    => [3, 2, 1],
    'bar'    => ['c', 'b', 'a'],
]

The sorted array should look like this:

[
    'sortBy' => [1, 2, 3],
    'other'  => ['z', 'y', 'x'],
    'xxx'    => [1, 2, 3],
    'foo'    => [1, 2, 3],
    'bar'    => ['a', 'b', 'c'],
]

Solution

  • You could use array_multisort() to good effect.

    $array = array(
        'sortBy' => array(3,   2,   1),
        'other'  => array('x', 'y', 'z'),
        'xxx'    => array(3,   2,   1),
    );
    
    array_multisort($array['sortBy'], SORT_NUMERIC, $array['other'], $array['xxx']);
    
    var_export($array);
    

    The above example prints the following:

    array (
      'sortBy' => 
      array (
        0 => 1,
        1 => 2,
        2 => 3,
      ),
      'other' => 
      array (
        0 => 'z',
        1 => 'y',
        2 => 'x',
      ),
      'xxx' => 
      array (
        0 => 1,
        1 => 2,
        2 => 3,
      ),
    )
    

    Edit

    Since you decided the array's keys could be anything (other than the one definite key: sortBy), then array_multisort() can still be used albeit called with a more dynamic list of arguments.

    $array = array( … );
    
    $args = array(&$array['sortBy'], SORT_NUMERIC);
    foreach ($array as $key => $value) {
        if ($key !== 'sortBy') {
            $args[] = &$array[$key];
        }
    }
    call_user_func_array('array_multisort', $args);
    unset($args);
    
    var_export($array);