Есть массив «движений» элементов, примерно одинаковый, только его может быть в разы больше:
Array
(
[0] => Array
(
[id] => 90415
[oldDate] => 2024-08-27
[newDate] => 2024-08-28
)
[1] => Array
(
[id] => 90415
[oldDate] => 2024-08-28
[newDate] => 2024-08-27
)
[2] => Array
(
[id] => 90409
[oldDate] => 2024-08-21
[newDate] => 2024-08-22
)
[3] => Array
(
[id] => 90409
[oldDate] => 2024-08-22
[newDate] => 2024-08-23
)
)
Я пытаюсь сделать так, чтобы все промежуточные перемещения элемента были удалены, остались только начальные и конечные, а также были удалены элементы массива, где элемент возвращается в исходное положение (0 и 1 элементы массив). В итоге обработанный массив должен выглядеть так:
Array
(
[0] => Array
(
[id] => 90409
[oldDate] => 2024-08-21
[newDate] => 2024-08-23
)
)
как это сделать, чтобы массив из большого количества элементов не задерживал выполнение скрипта на долгое время
Обработанный массив затем будет отправлен в отдельный метод, который продолжит с ним работать. Пытался это сделать, но не могу разобраться: 1) Как понять, что элемент newDate последний, и удалить все остальные элементы, оставив 2 значения, и нужно перебрать все элементы элемента массив, вам нужно составить регулярное выражение? 2) Как удалить только элементы с противоположными oldDate и newDate, оставив остальные с такими же ID
что вы в конечном итоге делаете с обработанным массивом? Я спрашиваю, потому что вы могли бы подумать о передаче массива в очередь сообщений для его асинхронной обработки, если вам не нужно возвращать его куда-то в текущем запросе. Таким образом, выполнение скрипта не будет задерживаться.
И еще: насколько велико большое? Мы говорим о 1000 или миллионах? миллиарды?
Отсортирован ли этот массив таким образом, чтобы мы могли быть уверены, что первое появление нового идентификатора сохранит его исходную позицию? Или может быть ['id' => 90409, 'oldDate' => '2024-08-20', 'newDate' => '2024-08-21'] после начального ['id' => 90409, 'oldDate' => '2024-08-22', 'newDate' => '2024-08-23'],?






Вот решение, использующее промежуточный ассоциативный массив $data, который обеспечивает эффективный поиск:
$moves = [
['id' => 90415, 'oldDate' => '2024-08-27', 'newDate' => '2024-08-28'],
['id' => 90415, 'oldDate' => '2024-08-28', 'newDate' => '2024-08-27'],
['id' => 90409, 'oldDate' => '2024-08-21', 'newDate' => '2024-08-22'],
['id' => 90409, 'oldDate' => '2024-08-22', 'newDate' => '2024-08-23'],
];
$data = [];
foreach($moves as $move)
{
$id = $move['id'];
if (isset($data[$id]))
{
// Id already present, update its newDate
$data[$id]['newDate'] = $move['newDate'];
}
else
{
// New id, store it
$data[$id] = $move;
}
}
// Keep ids with different oldDate and newDate
$result = array_filter($data, fn($move) => $move['oldDate'] != $move['newDate']);
// Remove array keys
$result = array_values($result);
var_export($result);
Выход:
array (
0 =>
array (
'id' => 90409,
'oldDate' => '2024-08-21',
'newDate' => '2024-08-23',
),
)
Просто для сравнения, вот функциональный эквивалент (безупречного) решения Оливье. Демо
var_export(
array_values(
array_filter(
array_reduce(
$movements,
function($carry, $move) {
$carry[$move['id']] ??= $move;
$carry[$move['id']]['newDate'] = $move['newDate'];
return $carry;
}
),
fn($move) => $move['oldDate'] != $move['newDate']
)
)
);
Это также можно записать так: Демо
$grouped = [];
foreach ($movements as $move) {
$grouped[$move['id']] ??= $move; // store if a new id
$grouped[$move['id']]['newDate'] = $move['newDate']; // overwrite stored newDate
}
var_export(
array_values(
array_filter(
$grouped,
fn($move) => $move['oldDate'] != $move['newDate']
)
)
);
определить «большое количество элементов». И что потом нужно делать с обработанным массивом? Нужно ли возвращать его пользователю, инициирующему вызов? Кроме того, что вы пробовали?