Как в Laravel найти элементы в коллекциях по определенному ключу и объединить их в новую коллекцию?

Здравствуйте! Я начал изучать коллекции и застрял на этом этапе на два дня. 

У меня есть две коллекции. Первая коллекция выглядит так:

<pre><code class="php">[
    "имя1" =&gt; "x",
    "объем1" =&gt; "x",
    "мусор" =&gt; "x",
    "мусор" =&gt; "x"
],
[
    "имя1" =&gt; "x",
    "объем1" =&gt; "x",
    "мусор" =&gt; "x",
    "мусор" =&gt; "x"
]</code></pre>

А вторая коллекция представлена следующим образом:

<pre><code class="php">[
    "имя2" =&gt; "x",
    "мусор" =&gt; "x",
    "объем2" =&gt; "x",
    "мусор" =&gt; "x"
],
[
    "имя2" =&gt; "x",
    "мусор" =&gt; "x",
    "объем2" =&gt; "x",
    "мусор" =&gt; "x"
]</code></pre>

У меня несколько таких коллекций. Обратите внимание, что ключи с нужными данными могут различаться, но общее количество данных, которые нужно извлечь, остается одинаковым. Длины коллекций также различны.

Я думал, что сначала следует привести названия ключей к единому формату, а затем перебрать нужные значения в новую коллекцию, но это меня сильно запутало.

В конечном итоге я хотел бы получить объединенную коллекцию, основанную на значении ключа "имя", добавив к этому значения "объем1" и "объем2".

Не могли бы вы мне помочь с этой задачей? =)
  • 18 сентября 2024 г. 16:33
Ответы на вопрос 2
Конечно! Давайте рассмотрим, как вы можете объединить две коллекции в Laravel на основе значения ключа "имя", добавив соответствующие значения объемов ("объем1" и "объем2").

Для этого можно использовать метод `collect()` для создания коллекций из массива и использовать методы `map()`, `filter()` и `merge()`, чтобы получить желаемый результат. Я покажу вам пример на основе вашего описания.

### Пример кода:

```php
use Illuminate\Support\Collection;

// Пример коллекций
$collection1 = collect([
    ['имя1' => 'ИмяA', 'объем1' => 10, 'мусор' => 'x'],
    ['имя1' => 'ИмяB', 'объем1' => 20, 'мусор' => 'x']
]);

$collection2 = collect([
    ['имя2' => 'ИмяA', 'объем2' => 30, 'мусор' => 'x'],
    ['имя2' => 'ИмяC', 'объем2' => 40, 'мусор' => 'x']
]);

// Создаем новую коллекцию, чтобы сохранить объединенные данные
$mergedCollection = collect();

// Обрабатываем первую коллекцию
$collection1->each(function ($item) use (&$mergedCollection) {
    $name = $item['имя1'];
    $volume1 = $item['объем1'];
    
    // Добавляем элемент в объединенную коллекцию
    $mergedCollection->put($name, [
        'имя' => $name,
        'объем1' => $volume1,
        'объем2' => 0 // Инициализируем объем2 как 0
    ]);
});

// Обрабатываем вторую коллекцию
$collection2->each(function ($item) use (&$mergedCollection) {
    $name = $item['имя2'];
    $volume2 = $item['объем2'];
    
    // Проверяем, существует ли имя в объединенной коллекции
    if ($mergedCollection->has($name)) {
        // Если существует, добавляем объем2 к существующему значению
        $existingItem = $mergedCollection->get($name);
        $existingItem['объем2'] = $volume2;
        
        $mergedCollection->put($name, $existingItem);
    } else {
        // Если не существует, добавляем новый элемент с объем1 как 0
        $mergedCollection->put($name, [
            'имя' => $name,
            'объем1' => 0, // Объем1 как 0
            'объем2' => $volume2
        ]);
    }
});

// Преобразуем объединенную коллекцию в массив для вывода
$resultArray = $mergedCollection->values()->toArray();

// Вывод результата
print_r($resultArray);
```

### Объяснение:

1. **Определение коллекций**: Мы создаем две коллекции `$collection1` и `$collection2`, которые будут содержать ваши данные.

2. **Инициализация новой коллекции**: Мы создаем пустую коллекцию `$mergedCollection`, в которую будем помещать объединенные данные.

3. **Обработка первой коллекции**: Мы используем метод `each()` для итерации по элементам первой коллекции. Для каждого элемента мы извлекаем имя и объем1 и добавляем новый элемент в объединённую коллекцию.

4. **Обработка второй коллекции**: Мы повторяем процесс для второй коллекции. Если имя уже существует в объединенной коллекции, мы добавляем значение `объем2` к ней. Если имя отсутствует, мы добавляем новый элемент.

5. **Вывод результата**: В конце мы преобразуем объединенную коллекцию в массив и выводим её.

После выполнения данного кода вы получите объединенную коллекцию, состоящую из значений, основанных на именах, с соответствующими объемами. 

Если у вас возникнут дополнительные вопросы или вам нужно больше примеров, не стесняйтесь спрашивать!
use Illuminate\Support\Collection;

$collection1 = collect([
    [
        "имя1" => "John",
        "объем1" => "100",
        "мусор" => "x"
    ],
    [
        "имя1" => "Jane",
        "объем1" => "200",
        "мусор" => "y"
    ]
]);

$collection2 = collect([
    [
        "имя2" => "John",
        "объем2" => "300",
        "мусор" => "x"
    ],
    [
        "имя2" => "Jane",
        "объем2" => "400",
        "мусор" => "z"
    ]
]);

function normalizeKeys(Collection $collection, $nameKey, $volumeKey)
{
    return $collection->map(function ($item) use ($nameKey, $volumeKey) {
        return [
            'name' => $item[$nameKey] ?? null,
            'volume' => $item[$volumeKey] ?? null,
        ];
    });
}

$normalized1 = normalizeKeys($collection1, 'имя1', 'объем1');
$normalized2 = normalizeKeys($collection2, 'имя2', 'объем2');

$result = $normalized1->map(function ($item1) use ($normalized2) {
    $match = $normalized2->firstWhere('name', $item1['name']);
    
    return [
        'name' => $item1['name'],
        'volume1' => $item1['volume'],
        'volume2' => $match['volume'] ?? null,
    ];
});
Похожие вопросы