I have this source array():
$source[]
[ ["user_id": 1, "item_id": 991, "quantity": 100], ["user_id": 1, "item_id": 992, "quantity": 50], ["user_id": 1, "item_id": 993, "quantity": 300], ["user_id": 1, "item_id": 992, "quantity": 150], ["user_id": 2, "item_id": 991, "quantity": 75], ["user_id": 2, "item_id": 992, "quantity": 20], ["user_id": 3, "item_id": 991, "quantity": 200], ["user_id": 3, "item_id": 992, "quantity": 425], ["user_id": 3, "item_id": 991, "quantity": 100], ["user_id": 3, "item_id": 992, "quantity": 75] ]
My goal is to reduce it so that i get only 1 item where user_id
& item_id
are the same:
$result[]
[ ["user_id": 1, "item_id": 991, "quantity": 100], ["user_id": 1, "item_id": 992, "quantity": 200], ["user_id": 1, "item_id": 993, "quantity": 300], ["user_id": 2, "item_id": 991, "quantity": 75], ["user_id": 2, "item_id": 992, "quantity": 20], ["user_id": 3, "item_id": 991, "quantity": 300], ["user_id": 3, "item_id": 992, "quantity": 500] ]
The ultimate way would be to use an array_reduce, but i’ll take a foreach loop.
I’ve tried this, but i get an empty array
$result = array_reduce($source, function($a, $b) { if (($a->user_id === $b->user_id) && ($a->item_id === $b->item_id)) { $a->quantity += $b->quantity; return $a; } else { return $b; } }, []);
or this, but i get an array with user_id
as index and quantity
as value as a overall total, not seperate by item_id
:
$result = array_reduce($source, function($a, $b) { (($a[$b["user_id"]] = $a[$b["user_id"]]) && ($a[$b["item_id"]] = $a[$b["item_id"]])) ?? 0; $a[$b["user_id"]] += $b["quantity"]; return $a; }, []);
I’m starting to try with a foreach
loop with if (isset[...])
but i feel like it will return true whatever the index of the $result[]
array.
Advertisement
Answer
You can use array_reduce
function in next way:
$res = array_reduce ( $source, function($res, $el) { if (isset($res[$el['user_id'].$el['item_id']])) { // if user_id with item_id exist // increase quantity by $el['quantity'] $res[$el['user_id'].$el['item_id']]['quantity'] += $el['quantity']; } else { // create record with unique key for each user_id & item_id // using concatenation $res[$el['user_id'].$el['item_id']] = $el; } return $res; }, [] // initial result - empty array ); // output result values without keys print_r(array_values($res));