After some playing around, this is the most 'laravel way' I could think of :
$input =[
['name' =>'John McClane','age'=>'40' ],
['name' =>'John McClane','age'=>'50' ],
['name' =>'Hans Gruber','age'=>'40' ],
['name' =>'Hans Gruber','age'=>'50' ],
['name' =>'Holly McClane','age'=>'20' ],
['name' =>'Holly McClane','age'=>'49' ],
];
$input = collect($input);
$data = $input->groupBy(function($row) {
return array_keys($row);
})->map(function($row, $key) {
return array_values(array_unique(array_pluck($row, $key)));
});
dd($data->toArray());
/**
*
* Outputs:
* array:2 [▼
* "name" => array:3 [▼
* 0 => "John McClane"
* 1 => "Hans Gruber"
* 2 => "Holly McClane"
* ]
* "age" => array:4 [▼
* 0 => "40"
* 1 => "50"
* 2 => "20"
* 3 => "49"
* ]
* ]
*/
(I added an array_values in there so you wont accidentally get an object instead of array when converting to json)
But to be clear, about the "... make this code any more efficient." part :
When we compare the actual code the version in your example is actually more efficient.
instead of 2 nested foreach loops and only assigning variables you want, we have now 'hidden' that second loop within array_pluck, which actually maps to Arr::pluck :
public static function pluck($array, $value, $key = null)
{
$results = [];
[$value, $key] = static::explodePluckParameters($value, $key);
foreach ($array as $item) {
$itemValue = data_get($item, $value);
if (is_null($key)) {
$results[] = $itemValue;
} else {
$itemKey = data_get($item, $key);
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
$itemKey = (string) $itemKey;
}
$results[$itemKey] = $itemValue;
}
}
return $results;
}
So, yeah... it looks nicer, but you're actually running more code / variables and checks now.