One possible solution is to use the reduce method on the collection to calculate the sum of the products and the sum of the coefficients, and then divide them to get the weighted average. Here's an example:
$collection = collect([
['value' => 10, 'coefficient' => 2],
['value' => 20, 'coefficient' => 3],
['value' => 30, 'coefficient' => 4],
]);
$weightedAverage = $collection->reduce(function ($carry, $item) {
return [
'sumProducts' => $carry['sumProducts'] + ($item['value'] * $item['coefficient']),
'sumCoefficients' => $carry['sumCoefficients'] + $item['coefficient'],
];
}, ['sumProducts' => 0, 'sumCoefficients' => 0]);
$weightedAverage = $weightedAverage['sumProducts'] / $weightedAverage['sumCoefficients'];
echo $weightedAverage; // Output: 23.333333333333
In this example, we have a collection of items with a value and a coefficient property. We use the reduce method to iterate over the collection and accumulate the sum of the products and the sum of the coefficients in an associative array. We initialize the accumulator with an array that has sumProducts and sumCoefficients set to zero.
After the reduce method finishes, we divide the sum of the products by the sum of the coefficients to get the weighted average.
This solution should be more performant than looping over the collection manually, especially for large collections.