I have an array that contains the key counted
and placement
which I am trying to group by before I sort. The array should be first sorted by counted
and then, for each duplicate counted
, should then sort by placement
.
$array = [
[
'id' => 1,
'placement' => 8,
'counted' => 3
'user' => ['name' => 'foo'],
],
[
'id' => 2,
'placement' => 5,
'counted' => 3
'user' => ['name' => 'bar'],
],
[
'id' => 3,
'placement' => 1,
'counted' => 2
'user' => ['name' => 'foobar'],
]
];
My expected output here would be:
$array = [
[
'id' => 2,
'placement' => 5,
'counted' => 3
'user' => ['name' => 'bar'],
],
[
'id' => 1,
'placement' => 8,
'counted' => 3
'user' => ['name' => 'foo'],
],
[
'id' => 3,
'placement' => 1,
'counted' => 2
'user' => ['name' => 'foobar'],
]
];
I have tried to usort
to achieve this:
usort($array, fn($a, $b) => ((int)$a['placement'] <=> (int)$b['counted']) * -1);
But this gives me an unexpected result. Everything I try seems to not work, any ideas would be appreciated.
CodePudding user response:
Since you prefer using usort so this is my answser
$array = [
[
'id' => 1,
'placement' => 8,
'counted' => 3,
'user' => ['name' => 'foo'],
],
[
'id' => 2,
'placement' => 5,
'counted' => 3,
'user' => ['name' => 'bar'],
],
[
'id' => 3,
'placement' => 1,
'counted' => 2,
'user' => ['name' => 'foobar'],
]
];
usort($array, function ($a, $b) {
if ($a['counted'] < $b['counted']) {
return 1;
}
if ($a['counted'] === $b['counted'] && $a['placement'] > $b['placement']) {
return 1;
}
});
CodePudding user response:
If you don’t care about efficiency, you can write like this
collect($array)
->sortByDesc('counted')
->groupBy('counted')
->map(function ($group) {
return $group->sortBy('placement');
})
->flatten(1)
->toArray()