Home > Software engineering >  Laravel collection merge from array based on item key value
Laravel collection merge from array based on item key value

Time:09-23

I have an array of $dates like below

[
    "2022-30",
    "2022-31",
    "2022-32",
    "2022-33",
    "2022-34",
    "2022-35",
]

and I have a $collection with an output like below

[
    {
        "new": 60,
        "settled": "1",
        "date": "2022-31"
    },
    {
        "new": 50,
        "settled": "1",
        "date": "2022-32"
    },
]

how can I achieve a result like below which merge the value of date from the $collection item if it matches from the date on $dates array

[
    {
        "new": 0,
        "settled": "0",
        "date": "2022-30"
    },
    {
        "new": 60,
        "settled": "1",
        "date": "2022-31"
    },
    {
        "new": 50,
        "settled": "1",
        "date": "2022-32"
    },
    {
        "new": 0,
        "settled": "0",
        "date": "2022-33"
    },
    {
        "new": 0,
        "settled": "0",
        "date": "2022-34"
    },
    {
        "new": 0,
        "settled": "0",
        "date": "2022-35"
    }
]

I tried making the dates into a collection and formatting the output like the $collection format and use merge but this just combine the two collection together with duplicates.

$out = collect($dates)->map( function($d, $k)  {
    return [
        'new' => 0,
        'settled' => 0,
        'date' => $d
    ];
});

return $out->merge($collection);

appreciate any help

CodePudding user response:

$dates = [
    "2022-30",
    "2022-31",
    "2022-32",
    "2022-33",
    "2022-34",
    "2022-35",
];

$collection = collect([
    [
        "new" => 60,
        "settled" => "1",
        "date" => "2022-31"
    ],
    [
        "new" => 50,
        "settled" => "1",
        "date" => "2022-32"
    ]
]);

foreach ($dates as $date) {
    if (!$collection->where('date', $date)->count()) {
        $collection->push([
                'new' => 0,
                'settled' => 0,
                'date' => $date
        ]);
    }
}

return $collection->sortBy('date')->values()->all();

CodePudding user response:

You can key the collection by dates and then add in the dates that are not in there:


$out = $collection->keyBy('date')
$out = $out->merge(
    collect($dates)
        ->whereNotIn(null, $out->keys())
        ->mapWithKeys(fn ($date) => [
            $date => [
                'new' => 0,
                'settled' => 0,
                'date' => $date
            ]
        ])
)->sortKeys()->values();

What this does is convert the collection to one that has the dates as keys, then filters from dates all the dates that are already in the collection, maps the rest into your desired format, sorts them all to how they should be then discards the keys.

CodePudding user response:

For the $dates maybe you can filter only the dates that does not exist in the collections? Then after you can map them out and merge.

  • Related