vguerrerobosch's avatar

Collection method to achieve the following

I would like to know how to achieve the following with Laravel Collections. Also would like to know what would be the name of this, just to replace this useless thread title. Thank you!

$items = [
    [
        'name' => 'Apple', 
        'color' => 'green',
        'code' => 'foo',
        'quantity' => 2
    ],
    [
        'name' => 'Orange',
        'color' => 'orange',
        'code' => 'bar',
        'quantity' => 1
    ],
    [
        'name' => 'Lemon',
        'color' => 'yellow',
        'code' => 'baz', 
        'quantity' => 3
    ]
];

$units = [];

foreach($items as $item) {
    for ($i=0; $i < $item['quantity']; $i++) {
        $units[] = [
            'code' => $item['code'] . '-' . ($i + 1),
            'name' => $item['name'],
            'color' => $item['color'],
        ];
    }
}

/*
    [
        ['code' => 'foo-1', 'name' => 'Apple', 'color' => 'green'],
        ['code' => 'foo-2', 'name' => 'Apple', 'color' => 'green'],
        ['code' => 'bar-1', 'name' => 'Orange', 'color' => 'orange'],
        ['code' => 'baz-1', 'name' => 'Lemon', 'color' => 'yellow'],
        ['code' => 'baz-2', 'name' => 'Lemon', 'color' => 'yellow'],
        ['code' => 'baz-3', 'name' => 'Lemon', 'color' => 'yellow']
    ]
*/
0 likes
6 replies
tykus's avatar
$units = collect($items)->map(function ($item) {
    return  [
        'name' => $item['name'],
        'color' => $item['color'],
    ];
});
ChristophHarms's avatar
$items = collect([
    collect(['name' => 'Apple',  'color' => 'green', 'quantity' => 2]),
    collect(['name' => 'Orange', 'color' => 'orange', 'quantity' => 1]),
    collect(['name' => 'Lemon', 'color' => 'yellow', 'quantity' => 3]),
]);

$withoutQty = $items->map->only(['name', 'color']);

return $withoutQty->toArray();
/*
[
     [
       "name" => "Apple",
       "color" => "green",
     ],
     [
       "name" => "Orange",
       "color" => "orange",
     ],
     [
       "name" => "Lemon",
       "color" => "yellow",
     ],
   ]
*/

Line 7 can be a bit confusing (at least it was to me) when you never heard of Higher Order Messages. Without Higher Order Messages, it would look like this:

$withoutQty = $items->map(function ($subCollection) {
        return $subCollection->only(['name', 'color']);
});

As for a name for this... I don't know, really. Filter out keys from sub-collections maybe?

vguerrerobosch's avatar

Thank you @tykus. I was just editing the question while you where posting your answer. In any case, I think map only doesn't achieve what it's wanted.

tykus's avatar
tykus
Best Answer
Level 104

You can use the index in the map:

$units = collect($items)->map(function ($item, $index) {
    return  [
'code' => $item['code'] . '-' $index+1,
        'name' => $item['name'],
        'color' => $item['color'],
    ];
});

EDIT just saw the update

collect($items)->flatMap(function ($item) {
    return collect()->times($item['quantity'])->map(function ($index) use ($item) {
        return  [
            'code' => $item['code'] . '-' . $index,
            'name' => $item['name'],
            'color' => $item['color'],
        ];
})->all();
});
2 likes

Please or to participate in this conversation.