codedge
codedge

Reputation: 5174

Restructuring collection items in Laravel

I've got the following Laravel collection of between 800 and 4000 items:

[
  {
    "date": "2017-05-26",
    "departure_time": "14:50:00",
    "arrival_time": "09:20:02",
    "departure_place_id": 16
  },
  {
    "date": "2017-05-26",
    "departure_time": "15:20:00",
    "arrival_time": "15:20:00",
    "departure_place_id": 15
  },
  ...
]

I need to merge always merge two items of the collection into one. So that a collection of 10 items, after merge, is a collection of 5 items with the follwing structure.

[
  {
     "date": "2017-05-26",
     "departure_time": "14:50:00", // from first item
     "arrival_time": "15:20:00", // from second item
     "departure_place_id": 16,  // from first item
     "arrival_place_id": 15 // from second item
  },
  ...
]

As you can see I need to merge data from two consecutive items to one.

I already tried two extend use Laravels custom collection feature but cannot really achieve what I want.

Any clue?

Upvotes: 0

Views: 689

Answers (3)

codedge
codedge

Reputation: 5174

After the tip from @Vikash with using chunk() and some research I came up with the following solution which suits my needs best:

public function convert() : \Illuminate\Support\Collection 
{
    /** @var \Illuminate\Database\Eloquent\Collection $collection */
    $collection = $this->cruise->where('line_id', $lineId)->get();

    return $collection->chunk(2)->map(function ($chunk) {
                /** @var Collection $chunk */
                return [
                    'date' => $chunk->first()->date,
                    'downriver' => $chunk->last()->departure_place_id < $this->departure_place_id,
                    'departure_time' => $chunk->first()->departure_time,
                    'arrival_time' => $chunk->last()->departure_time,
                    'departure_place_id' => $chunk->first()->departure_place_id,
                    'arrival_place_id' => $chunk->last()->departure_place_id,
                ];
            });
}

I put that into a repository which is a nice way to decouple the logic. It utilizes the collection functions instead of dealing with arrays which I definately wanted to avoid.

Upvotes: 0

Vikash
Vikash

Reputation: 3551

You can solve it by using laravel collection chunk

 public function formatCollection($collection)
 {
  $results = [];
     foreach (collect($collection)->chunk(2) as $chunk)
     {
         $results[] = [
             'date' => $chunk[0]['date'],
             'departure_time' => $chunk[0]['departure_time'],
             'arrival_time' => $chunk[1]['arrival_time'],
             'departure_place_id'=> $chunk[0]['departure_place_id'],
             'arrival_place_id' => $chunk[1]['departure_place_id']
         ];
     }

    return collect($results);
 }

Call this function to format the data

Upvotes: 1

Robin Choffardet
Robin Choffardet

Reputation: 460

IMO, if you only had two items, you should create a class which will "merge" your two items in one as you do.

Collection are made to treat a collection of items, so 1 to N items not only two.

Upvotes: 0

Related Questions