Как сохранить вложенные массивы при слиянии Laravel коллекции - PullRequest
0 голосов
/ 26 мая 2020

Я схожу с ума от этого.

Учитывая, что у меня есть 2 массива, например


$array1 = [
    "data_to_merge" => ["2020-03-11 16:00:00", "2020-03-24 14:00:00"],
    "data_to_merge_past_year" => ["2019-03-11 16:00:00"],
];

$array2 = [
    "data_to_merge" => [],
    "data_to_merge_past_year" => ["2018-03-11 14:00:00"],
];

Моя цель - получить результат вроде

all: [
       "data_to_merge" => [
         "2020-03-11 16:00:00",
         "2020-03-24 14:00:00"
       ],
       "data_to_merge_past_year" => [
         "2018-03-11 14:00:00",
         "2018-03-11 16:00:00",
       ],
     ],

Я пробовал просто с

$result = collect($array1)->merge(collect($array2));

Но при таком подходе он удалит значения из data_to_merge из моего первого массива. Есть ли способ Laravel получить такой результат? Для демонстрации может быть больше двух массивов.

Вот мой полный пример, в основном тот же


$array1 = [
    "host" => "blablubb",
    "data_to_merge" => [
      "2020-03-11 16:00:00",
      "2020-03-24 14:00:00"
    ],
    "data_to_merge_past_year" => [
      "2019-03-11 16:00:00"
    ],
];

$array2 = [
    "host" => "blablubb",
    "data_to_merge" => [],
    "data_to_merge_past_year" => [
      "2018-03-11 16:00:00"
    ],
];

$array3 = [
    "host" => "blablubb",
    "data_to_merge" => [],
    "data_to_merge_past_year" => [],
];

$array4 = [
    "host" => "blablubb",
    "data_to_merge" => [
      "2020-03-04 14:00:00",
      "2020-03-04 17:00:00"
    ],
    "data_to_merge_past_year" => [],
];



$all = collect([$array1, $array2, $array3, $array4]);

$all
    ->groupBy('host')
    ->map(function ($item) {
        if (count($item) > 1) {
            $result = collect([]);

            foreach ($item as $subItem) {
                $result = $result->merge($subItem);
            }
            return $result;
        }

        return $item->first();
    })
    ->values()
    ->toArray();

Спасибо, ребята!

1 Ответ

2 голосов
/ 26 мая 2020

Вы можете использовать mergeRecursive для этого:

$array1 = [
    "data_to_merge" => ["2020-03-11 16:00:00", "2020-03-24 14:00:00"],
    "data_to_merge_past_year" => ["2019-03-11 16:00:00"],
];

$array2 = [
    "data_to_merge" => [],
    "data_to_merge_past_year" => ["2018-03-11 14:00:00"],
];

$result = collect($array1)->mergeRecursive(collect($array2));

Результат:

Illuminate\Support\Collection {#1278 ▼
  #items: array:2 [▼
    "data_to_merge" => array:2 [▼
      0 => "2020-03-11 16:00:00"
      1 => "2020-03-24 14:00:00"
    ]
    "data_to_merge_past_year" => array:2 [▼
      0 => "2019-03-11 16:00:00"
      1 => "2018-03-11 14:00:00"
    ]
  ]
}

Из документов:

The mergeRecursive рекурсивно объединяет данный массив или коллекцию с исходной коллекцией. Если строковый ключ в данных элементах совпадает со строковым ключом в исходной коллекции, тогда значения этих ключей объединяются в массив, и это делается рекурсивно:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->mergeRecursive(['product_id' => 2, 'price' => 200, 'discount' => false]);

$merged->all();

// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
...