Как объединить ассоциативных массива по значению полей?
есть два массива, у которых есть поле "date" и есть показатели, например, price и quantity
как объединить эти массивы по полю date так чтобы показатели price и quantity при этом сложились?
$dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], ]; $dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 0 ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; $result = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; |
$dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], ]; $dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 0 ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; $result = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], [ 'date' => "03.08.2023", 'qty' => 25, ], ];
Дополнительно:
Пройти оба циклом, создавая новый массив, где date - ключ, а значения - price и quality, суммирующиеся, если они уже есть. Особенно актуально, если date не уникален.
Впрочем, вопрос безобразно неконкретен и может предполагать кучу разных вариантов того, что реально нужно ТС.
$dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], ]; $dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 0 ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; $result = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; |
$dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], ]; $dates1[] = [ [ 'date' => "01.08.2023", 'qty' => 0 ], [ 'date' => "03.08.2023", 'qty' => 25, ], ]; $result = [ [ 'date' => "01.08.2023", 'qty' => 100 ], [ 'date' => "02.08.2023", 'qty' => 15, ], [ 'date' => "03.08.2023", 'qty' => 25, ], ];
у меня решение получилось таким:
один внешний цикл. перебирает один массив. и внутри цикла используется второй массив преобразованный в коллекцию. и при помощи функции filter ищется элемент с таким же полем "date".
если находим элемент, то объединяем элементы, то в третий массив добавляем этот элемент суммируя qty.
а если не находим, то записываем элемент внешнего цикла.
А ламерский подход - это формулировать задачу про
price и quantity
и при этом давать в качестве примера
[ 'date' => "01.08.2023", 'qty' => 100 ] |
[ 'date' => "01.08.2023", 'qty' => 100 ]
и даже не задуматься о том, могут даты продублироваться или нет.
Подход профи - напротив, задуматься, что будет, КОГДА они задублируются, ХОТЯ вы были уверены, что этого не может быть.
собственно стоит загуглить 3 варианта соединения - nested loop join, merge join, hash join и это в разы будет лучше чем заучивание каких либо глупостей в виде методов коллекций ларки. заодно будете лучше понимать explain запросов к бд.
а так то да - в цикле всё легко делается.
1. и в последний раз: сеньора отличает не знание и использование каких то конкретных инструментов, а знание как работают эти инструменты и следовательно когда стоит их использовать, а когда стоит выбрать другие. Собственно если вы в ответах начнете усложнять контекст задачи а именно к примеру укажите что массивы большие, и сортированные, а процесс частый - эти красивые комбайны быстро трансформируются в нечто другое - похожее на то что я рекомендовал вам почитать. Ибо скорее всего поймут что такое количество циклов здесь не нужно. Но больше я эту тему поднимать не буду - мне лень, подожду когда вы попадете в более менее нормальную контору и вас там за эту глупость показательно накажут.
2. И если у вас postgresql вы занимаетесь фигней. ибо в нем есть прекрасная функция generate_series
select dates, colaesce(quantity, 0) from generate_series('2023-01-01', '2023-12-31', interval '1 day') as dates left join table_with_data on dates = table_with_data.date; |
select dates, colaesce(quantity, 0) from generate_series('2023-01-01', '2023-12-31', interval '1 day') as dates left join table_with_data on dates = table_with_data.date;
сразу из дб вернет вам то что нужно и весь этот гемморой уйдет в историю
function merge($arrs, $idKey, ...$sumKeys) { $result = []; foreach (array_merge(...$arrs) as $n) { $id = $n[$idKey]; $result[$id] ??= array_merge($n, array_combine($sumKeys, array_fill(0, count($sumKeys), 0))); foreach ($sumKeys as $k) { $result[$id][$k] += $n[$k]; } } return array_values($result); } $result = merge($dates1, 'date', 'qty'); |
function merge($arrs, $idKey, ...$sumKeys) { $result = []; foreach (array_merge(...$arrs) as $n) { $id = $n[$idKey]; $result[$id] ??= array_merge($n, array_combine($sumKeys, array_fill(0, count($sumKeys), 0))); foreach ($sumKeys as $k) { $result[$id][$k] += $n[$k]; } } return array_values($result); } $result = merge($dates1, 'date', 'qty');
function merge($arr) { $map = array_reduce(array_merge(...$arr), function($map, $item) { $map[$item["date"]] = ($map[$item["date"]] ?? 0) + $item["qty"]; return $map; }, []); return array_map(function($key) use ($map) { return [ "date" => $key, "qty" => $map[$key], ]; }, array_keys($map)); } |
function merge($arr) { $map = array_reduce(array_merge(...$arr), function($map, $item) { $map[$item["date"]] = ($map[$item["date"]] ?? 0) + $item["qty"]; return $map; }, []); return array_map(function($key) use ($map) { return [ "date" => $key, "qty" => $map[$key], ]; }, array_keys($map)); }
Упарываться можно по разному, например смапить по ключу, а потом переформировать в нужную структуру.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для объединения ассоциативных массивов по значениям определенных полей, можно воспользоваться функцией array_merge_recursive(). Эта функция объединяет два или более массивов рекурсивно, сохраняя все значения и структуру массивов.
Пример использования:
$array1 = array( array("id" => 1, "name" => "John"), array("id" => 2, "name" => "Alice") ); $array2 = array( array("id" => 2, "age" => 25), array("id" => 1, "age" => 30) ); $result = array(); foreach ($array1 as $item1) { foreach ($array2 as $item2) { if ($item1['id'] == $item2['id']) { $result[] = array_merge_recursive($item1, $item2); break; } } } print_r($result);
В данном примере мы объединяем массивы $array1 и $array2 по значению поля 'id'. Мы проходим по каждому элементу массива $array1 и сравниваем его 'id' со всеми элементами массива $array2. При совпадении значений 'id' мы объединяем элементы в новый массив $result с помощью функции array_merge_recursive().
После выполнения этого кода, в переменной $result будет содержаться объединенный массив, который можно использовать дальше в программе.