0

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.

1 Answer 1

2

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));

PHP array_reduce online

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, so you are creating the $result array with custom index by concatenating user_id and item_id, then you get rid of this index with array_values. Nice, i'll give it a try
You can look a working code sample online phpize.online/sql/mysql57/undefined/php/php8/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.