Php, usort () не работает, когда я хочу заказать в порядке - PullRequest
0 голосов
/ 12 апреля 2020

позволяет иметь начальный массив:

$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],
];

Я хочу упорядочить его по date , и, если даты равны, упорядочить по roundIndex . Учтите, что «roundIndex» может не существовать.

Первый:

usort($hits, static function(array $item1, array $item2) {
    return $item1['date'] < $item2['date'] ? -1 : 1;
});

Результат:

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

пока все хорошо. Итак, 2-я сортировка:

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;
    });

результат теперь немного облажался:

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

Я действительно не понимаю, почему. Но если я закажу вручную:

$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;
            }
        }
    }
}

ВСЕ, результат будет идеальным! Но будет 10000 элементов, и было измерено, что при заказе вручную это занимает 20-30 секунд ...

здесь вы можете попробовать это: https://ideone.com/ZaV5Ar

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Извините за чрезвычайно сжатое решение, но оно в основном сравнивает даты, используя оператор космического корабля (<=>), и если результат сравнения дат равен false (то есть они равны), то он возвращает сравнение значений roundIndex. ..

usort($hits, function($a,$b) {
    return $a['date'] <=> $b['date'] ?: 
         ($a['roundIndex']??0) <=> ($b['roundIndex']??0);
});
1 голос
/ 12 апреля 2020

Полагаю, этого достаточно:

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'];
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...