问题
I need to sort the following array with following logic: If the 'score' is the same, I want to compare using 'time'. The array is as follows:
$user_scores = [ 82 => [ 'score' => 1, 'time' => 6.442 ],
34 => [ 'score' => 1, 'time' => 5.646 ],
66 => [ 'score' => 3, 'time' => 1.554 ]
]
The 'keys' in the above array are the 'user_ids', which I need to preserve in the sorted array. My best attempt so far is as below -
$result = usort( $user_scores, function ( $a, $b ) {
if ( $a['score'] == $b['score'] ) {
return $a['time'] == $b['time'];
}
return $a['score'] <=> $b['score'];
} );
Obviously, this isn't working, and I'm getting the $user_scores array with all keys replaced with 0, 1, 2 instead of user_ids ( 82, 34 and 66 ). The sorting ain't working either.
For the above array, my desired output would be $user_scores array :
$user_scores = [ 34 => [ 'score' => 1, 'time' => 5.646 ],
82 => [ 'score' => 1, 'time' => 6.442 ],
66 => [ 'score' => 3, 'time' => 1.554 ]
]
Would really appreciate if you could tell me how to make this work using the spaceship operator (if it makes sense). Thank you for your time and I look forward to your responses.
---UPDATE ---
The sorting logic required is like this:
- Higher the score, higher would be the rank.
- Higher the time, lower would be the rank.
It's basically sorting the results of quiz. The top scorers with the least amount of time would be at the top; and those with lower score and higher time would be at the bottom.
回答1:
To preserve the keys, you just need to use uasort()
.
I recommend the spaceship operator to make the 3-way comparisons (available from PHP7 and higher).
$result
in your code is only going to return true/false
so that is no use to you. The sort()
'ing functions aren't to be assigned to a variable; they directly modify the input array.
When offering array data to the spaceship operator, the first two elements will be compared. If there is a difference, then 1
or -1
will be returned. If there is a tie (comparison evaluates as 0
, then the next two elements will be evaluated. This behavior continues until a non-zero evaluation occurs or there are no more elements to iterate. This is a rather clean/readable syntax to implement.
To sort in a descending direction, write the $b
value on the left and the $a
value on the right.
Code: (Demo)
$user_scores = [
82 => ['score' => 1, 'time' => 6.442],
34 => ['score' => 1, 'time' => 5.646],
66 => ['score' => 3, 'time' => 1.554],
7 => ['score' => 2, 'time' => 4.442],
99 => ['score' => 4, 'time' => 3.646],
55 => ['score' => 1, 'time' => 2.554]
];
uasort($user_scores, function($a, $b) {
return [$b['score'], $a['time']] <=> [$a['score'], $b['time']];
});
var_export($user_scores);
Output:
array (
99 =>
array (
'score' => 4,
'time' => 3.646,
),
66 =>
array (
'score' => 3,
'time' => 1.554,
),
7 =>
array (
'score' => 2,
'time' => 4.442,
),
55 =>
array (
'score' => 1,
'time' => 2.554,
),
34 =>
array (
'score' => 1,
'time' => 5.646,
),
82 =>
array (
'score' => 1,
'time' => 6.442,
),
)
来源:https://stackoverflow.com/questions/44309585/properly-sorting-multidimensional-array-using-usort-and-spaceship-operator