Сортировка по штрафам в массиве через рокировки
такая проблема: никак не пойму как сделать реализацию сортировки по штрафам, при этом по бонусам сделать получилось.
Дано: двумерный массив пользователей, у каждого есть id, имя, стартовая позиция и модификатор (если отрицательный то бонус, если положительный то штраф).
Как работают бонусы: например, есть очередь из пользователей Test1, Test2, Test3. Если пользователю Test3 прописать бонус 1, то он поменяется местами с пользователем Test2 и получится Test1, Test3, Test2. Если поставить бонус 2, то он станет первым.
Штрафы работают наоборот. Если пользователю Test1 прописать штраф 3, он переместится в конец очереди.
Вот мой работающий код для бонусов:
<?
$new = array(); $orders = array();
$new[111]['position'] = 1; $new[111]['user'] = 'Test1'; $orders[1] = 111; $new[111]['shift'] = 0;
$new[222]['position'] = 2; $new[222]['user'] = 'Test2'; $orders[2] = 222; $new[222]['shift'] = 0;
$new[333]['position'] = 3; $new[333]['user'] = 'Test3'; $orders[3] = 333; $new[333]['shift'] = 0;
$new[444]['position'] = 4; $new[444]['user'] = 'Test4'; $orders[4] = 444; $new[444]['shift'] = 0;
$new[555]['position'] = 5; $new[555]['user'] = 'Test5'; $orders[5] = 555; $new[555]['shift'] = 0;
$new[666]['position'] = 6; $new[666]['user'] = 'Test6'; $orders[6] = 666; $new[666]['shift'] = 0;
$new[777]['position'] = 7; $new[777]['user'] = 'Test7'; $orders[7] = 777; $new[777]['shift'] = 0;
$new[888]['position'] = 8; $new[888]['user'] = 'Test8'; $orders[8] = 888; $new[888]['shift'] = 0;
//функция для сдвига
function bonus($start, $bonus)
{
global $new, $orders;
//для бонусов, сдвиг в начало, $bonus отрицательное число
if ($bonus < 0)
{
for ($i = $start; $i > ($start - abs($bonus)); $i--)
{
$order_id = intval($orders[$i]);
$prev = intval($orders[$i - 1]);
if ($prev != 0)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$prev]['position'];
$new[$prev]['position'] = $temp;
$orders[$i] = $prev;
$orders[$i - 1] = $order_id;
}
}
}
//конец для бонусов
}
//Задаю вручную штрафы (бонусы отрицательные, штрафы положительные)
$new[555]['shift'] = -2;
//сортирую по бонусам
$i = 1;
foreach($new as $value)
{
$order_id = $orders[$i];
bonus($new[$order_id]['position'], $new[$order_id]['shift']);
$i++;
}
//сортировка двумерного массива по полю позиция
usort($new, function($a, $b){
return $a['position'] <=> $b['position'];
});
//ВЫВОД ДАННЫХ
$i = 1;
foreach($new as $value)
{
echo $i . '. ' . $value['user'] . ' ; сдвиг: ' . $value['shift'];
echo '<br>';
$i++;
}
?>
Здесь бонус задаётся через $new[555]['shift'] = -2;
Соответственно, штраф будет выглядеть как $new[444]['shift'] = 3;
Код для штрафов вроде бы должен выглядеть как-то так:
//для штрафов, сдвиг в конец, $bonus положительное число
if ($bonus > 0)
{
$total_new = count($new);
for ($i = $start; $i < ($start + $bonus); $i++)
{
$order_id = intval($orders[$i]);
$next = intval($orders[$i + 1]);
if ($next < $total_new)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$next]['position'];
$new[$next]['position'] = $temp;
$orders[$i] = $next;
$orders[$i + 1] = $order_id;
}
}
}
//конец для штрафов
Только менять массив $orders надо как-то по-другому. Я попробовал много разных вариаций, включая проход массива наоборот, с конца, но корректной работы не добился...
Ответы (1 шт):
Приведите структуру массива в порядок, тогда сортировать можно будет без "соток/гектар" ненужного кода.
$new = [
'111' => [
'position' => 1,
'user' => 'Test1',
'shift' => 0
],
'222' => [
'position' => 2,
'user' => 'Test2',
'shift' => 0
],
'333' => [
'position' => 3,
'user' => 'Test2',
'shift' => 0
]
];
$new[111]['shift'] = -3;
array_multisort(array_column($new, 'shift'), SORT_DESC, SORT_NUMERIC, $new);