Reputation: 6207
lets have an initial array:
$hits = [
['date' => new \DateTime('2019-01-02 12:00:00'), 'roundIndex' => 1],
['date' => new \DateTime('2019-01-02 12:00:00'), 'roundIndex' => 4],
['date' => new \DateTime('2019-01-02 12:00:00'), 'roundIndex' => 2],
['date' => new \DateTime('2019-01-02 12:00:00'), 'roundIndex' => 1],
['date' => new \DateTime('2019-01-01 12:00:00'), 'roundIndex' => 1],
['date' => new \DateTime('2019-01-04 12:00:00'), 'roundIndex' => 4],
['date' => new \DateTime('2019-01-02 12:00:00'), 'roundIndex' => 2],
['date' => new \DateTime('2019-01-23 12:00:00'), 'roundIndex' => 1],
['date' => new \DateTime('2019-01-22 12:00:00'), 'roundIndex' => 6],
['date' => new \DateTime('2019-01-01 12:00:00'), 'roundIndex' => 3],
['date' => new \DateTime('2019-01-06 12:00:00'), 'roundIndex' => 2],
['date' => new \DateTime('2019-01-28 12:00:00'), 'roundIndex' => 7],
['date' => new \DateTime('2019-01-26 12:00:00'), 'roundIndex' => 3],
['date' => new \DateTime('2019-01-27 12:00:00'), 'roundIndex' => 5],
['date' => new \DateTime('2019-01-26 12:00:00'), 'roundIndex' => 2],
['date' => new \DateTime('2019-01-11 12:00:00'), 'roundIndex' => 4],
['date' => new \DateTime('2019-01-24 12:00:00'), 'roundIndex' => 3],
['date' => new \DateTime('2019-01-08 12:00:00'), 'roundIndex' => 7],
['date' => new \DateTime('2019-01-11 12:00:00'), 'roundIndex' => 8],
['date' => new \DateTime('2019-01-14 12:00:00'), 'roundIndex' => 6],
['date' => new \DateTime('2019-01-13 12:00:00'), 'roundIndex' => 4],
['date' => new \DateTime('2019-01-13 12:00:00'), 'roundIndex' => 5],
['date' => new \DateTime('2019-01-24 12:00:00'), 'roundIndex' => 2],
['date' => new \DateTime('2019-01-27 12:00:00'), 'roundIndex' => 4],
];
I want to order it by date, and if dates are equal, order by roundIndex. Take into account that "roundIndex" might not exists.
First:
usort($hits, static function(array $item1, array $item2) {
return $item1['date'] < $item2['date'] ? -1 : 1;
});
the result is:
2019-01-01 12:00:00 1
2019-01-01 12:00:00 3
2019-01-02 12:00:00 4
2019-01-02 12:00:00 2
2019-01-02 12:00:00 1
2019-01-02 12:00:00 2
2019-01-02 12:00:00 1
2019-01-04 12:00:00 4
2019-01-06 12:00:00 2
2019-01-08 12:00:00 7
2019-01-11 12:00:00 8
2019-01-11 12:00:00 4
2019-01-13 12:00:00 5
2019-01-13 12:00:00 4
2019-01-14 12:00:00 6
2019-01-22 12:00:00 6
2019-01-23 12:00:00 1
2019-01-24 12:00:00 3
2019-01-24 12:00:00 2
2019-01-26 12:00:00 2
2019-01-26 12:00:00 3
2019-01-27 12:00:00 4
2019-01-27 12:00:00 5
2019-01-28 12:00:00 7
so far so good. So the 2nd sorting:
usort($hits, function($a,$b) use ($defaults) {
if (
$a['date']->format('Y-m-d H:i:s') === $b['date']->format('Y-m-d H:i:s'))
{
if ($a['roundIndex'] > $b['roundIndex'])
{
return 1;
}
else
{
return -1;
}
}
return 0;
});
the result is now a bit screwed up:
2019-01-08 12:00:00 7
2019-01-04 12:00:00 4
2019-01-06 12:00:00 2
2019-01-02 12:00:00 1
2019-01-02 12:00:00 1
2019-01-02 12:00:00 2
2019-01-02 12:00:00 2
2019-01-02 12:00:00 4
2019-01-11 12:00:00 4
2019-01-11 12:00:00 8
2019-01-27 12:00:00 4
2019-01-26 12:00:00 3
2019-01-24 12:00:00 2
2019-01-26 12:00:00 2
2019-01-23 12:00:00 1
2019-01-24 12:00:00 3
2019-01-22 12:00:00 6
2019-01-14 12:00:00 6
2019-01-13 12:00:00 4
2019-01-13 12:00:00 5
2019-01-01 12:00:00 3
2019-01-27 12:00:00 5
2019-01-28 12:00:00 7
2019-01-01 12:00:00 1
I dont really understand, why. But if I manually order:
$sizeOfHits = sizeof($hits);
for($i = 0; $i < $sizeOfHits; $i++)
{
for($j = $i+1; $j < $sizeOfHits; $j++)
{
if (
$hits[$i]['date']->format('Y-m-d H:i:s') === $hits[$j]['date']->format('Y-m-d H:i:s'))
{
if ($hits[$i]['roundIndex'] > $hits[$j]['roundIndex'])
{
$x = $hits[$j];
$hits[$j] = $hits[$i];
$hits[$i] = $x;
}
}
}
}
ALL the result is perfect! But there will be 10000 elements, and it was measured that by ordering manually, it takes 20-30 seconds...
here you can try this out: https://ideone.com/ZaV5Ar
Upvotes: 0
Views: 91
Reputation: 57131
Excuse the extremely terse solution, but it basically compares the dates using the spaceship operator (<=>
) and if the result of comparing the dates is false (i.e. they are equal) then it returns the comparison of the roundIndex values...
usort($hits, function($a,$b) {
return $a['date'] <=> $b['date'] ?:
($a['roundIndex']??0) <=> ($b['roundIndex']??0);
});
Upvotes: 1
Reputation: 54831
I suppose this is enough:
usort($hits, function($a, $b) {
// You can compare DateTime objects directly
if ($a['date'] == $b['date']) {
// use ?? to check if `roundIndex` exists
return ($a['roundIndex'] ?? 0) - ($b['roundIndex'] ?? 0);
}
return $a['date'] > $b['date'];
});
Upvotes: 1