0

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'],
]
1

2 Answers 2

2

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);
Sign up to request clarification or add additional context in comments.

4 Comments

I cannot call this function like that, because I don't know all the possible keys, only the sortBy key is known, all other keys are random.
Then use call_user_func_array() with an appropriate array of arguments (see edit).
Works without "if ($key !== 'sortBy')", but I'll add it just to be safe :)
Yes, it would work but it would be doing extra sorting that is not needed.
0

Build an array of parameters for array_multisort(). Start with the highest priority rows and if there are multiple priorities, work your way down. Ascending sorting directions don't need to be mentioned, but for a descending sort, push SORT_DESC as a parameter. After the sorting parameters, push references to the all of the original associatively-keyed rows.

To sort by the first row in an ascending direction: Demo

$params = [];
foreach ($array as &$params[]);
array_multisort(...$params);
var_export($array);

Or to sort by order in a descending direction: Demo

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

$params[] = $array['other'];
$params[] = SORT_DESC;
foreach ($array as &$params[]);
array_multisort(...$params);

var_export($array);

Output:

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,
  ),
  'foo' => 
  array (
    0 => 1,
    1 => 2,
    2 => 3,
  ),
  'bar' => 
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
)

Note that there are any ties to break, the following array parameter will be used.


For a stable sort which will ONLY mutate the array by other sorting, preserve the keys while sorting the other row, then loop over all of the rows and use the new index orders as the basis for all values. array_replace() will see that the values are written to the correct keys. Demo

arsort($array['other']);
var_export(
    array_map(
        fn($row) => array_replace(
            $array['other'],
            $row
        ),
        $array
    )
);

Same output as the previous other-sorting script.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.