$data = [
[
"id" => 57,
"order_id" => 51,
"order_hash" => "1234WEDK",
"price" => 600
],
[
"id" => 58,
"order_id" => 51,
"order_hash" => "1234WEDK",
"price" => 500
],
[
"id" => 59,
"order_id" => 1111,
"order_hash" => "1234ABCD",
"price" => 200
]
];
$result = array_reduce($data, function($acc, $x) {
if (!array_key_exists($x['order_hash'], $acc)) {
$acc[$x['order_hash']] = 0;
}
$acc[$x['order_hash']] += $x['price'];
return $acc;
}, []);
echo json_encode($result, JSON_PRETTY_PRINT), PHP_EOL;
Output
{
"1234WEDK": 1100,
"1234ABCD": 200
}
That solution is mostly crap tho because the function is totally tangled up with multiple intentions and responsibilities. It's looking up object properties, grouping, and summing values all in one. Blech.
Functional Programming in PHP can be pretty verbose, but that doesn't mean it should be entirely dismissed.
What if I told you … the entire solution could be reduced to this ?
// your reusable computation
$sumOrdersByHash = comp (map (function($xs) {
return [
'hash' => prop ('order_hash') (head ($xs)),
'sum' => sum (map (prop('price')) ($xs))
];
})) (group_by (prop ('order_hash')));
// run computation
$result = $sumOrdersByHash($data);
All you need are these reusable prerequisites. Bwahahahaha …
function id ($x) { return $x; }
function head ($xs) { return $xs[0]; }
function tail ($xs) { return array_slice($xs, 1); }
function foldl (callable $f) {
return function ($acc) use ($f) {
return function ($xs) use ($f, $acc) {
if (empty($xs))
return $acc;
else
return foldl ($f) (call_user_func($f, $acc, head($xs))) (tail ($xs));
};
};
}
function map (callable $f) {
return foldl (function ($acc, $x) use ($f) {
return array_merge($acc, [call_user_func($f, $x)]);
}) ([]);
}
function sum ($xs) {
return foldl (function ($x, $y) { return $x + $y; }) (0) ($xs);
}
function prop ($k) {
return function ($arr) use ($k) {
return $arr[$k];
};
};
function group_by (callable $f) {
return foldl (function ($acc, $x) use ($f) {
$key = call_user_func($f, $x);
if (array_key_exists($key, $acc))
array_push($acc[$key], $x);
else
$acc[$key] = [$x];
return $acc;
}) ([]);
}
function comp (callable $f) {
return function (callable $g) use ($f) {
return function ($x) use ($f, $g) {
return call_user_func($f, call_user_func($g, $x));
};
};
}
Put it all together and here's what you get
$result = $sumOrdersByHash($data);
echo json_encode($result, JSON_PRETTY_PRINT), PHP_EOL;
// =>
[
{
"hash": "1234WEDK",
"sum": 1100
},
{
"hash": "1234ABCD",
"sum": 200
}
]