Home > Software engineering >  How to group PHP arrays by key before sorting by another key?
How to group PHP arrays by key before sorting by another key?

Time:12-04

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()
  • Related