0

I have this array data:

array:3 [
  0 => array:5 [
    "menu_id" => 7
    "menu_name" => "Kasagbutan Meals"
    "menu_price" => "100.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
  1 => array:5 [
    "menu_id" => 7
    "menu_name" => "Kasagbutan Meals"
    "menu_price" => "100.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
  2 => array:5 [
    "menu_id" => 6
    "menu_name" => "Coke"
    "menu_price" => "50.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
]

When I ran it with array_unique(), the data becomes like this:

array:2 [
  0 => array:5 [
    "menu_id" => 7
    "menu_name" => "Kasagbutan Meals"
    "menu_price" => "100.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
  2 => array:5 [
    "menu_id" => 6
    "menu_name" => "Coke"
    "menu_price" => "50.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
]

How can I add the qty before it reduces the array? I want to add the qty of the removed array item. So basically, the ideal array result should be like this:

array:2 [
  0 => array:5 [
    "menu_id" => 7
    "menu_name" => "Kasagbutan Meals"
    "menu_price" => "100.00"
    "qty" => "2" ----> THIS BECOMES 2 BECAUSE THE OTHER ITEM HAS A QTY OF 1.
    "special_instructions" => ""
  ]
  2 => array:5 [
    "menu_id" => 6
    "menu_name" => "Coke"
    "menu_price" => "50.00"
    "qty" => "1"
    "special_instructions" => ""
  ]
]
PinoyStackOverflower
  • 5,214
  • 18
  • 63
  • 126
  • Are you obtaining that data from a relational/nosql database? – Fabrizio Valencia Jul 06 '20 at 02:16
  • What makes one entry equal to another? Just the `menu_id` property or does it take into account other properties too? – Phil Jul 06 '20 at 02:17
  • @Phil - If they have the same values in the following keys: - menu_id - menu_name - menu_price - special_instructions So basically all EXCEPT `qty` – PinoyStackOverflower Jul 06 '20 at 02:21
  • So you're saying entries can have the same `menu_id` but different `menu_name`, `menu_price`, etc? What's the point in having a field named _"id"_ if it doesn't identify the record? – Phil Jul 06 '20 at 02:23
  • @Phil - Actually, No. Ideally if they have the same `menu_id` it will also have the same `menu_name`, `menu_price`, etc.. I am including `menu_id` because I am returning this data in the frontend and my JS code is doing some logic in this also. – PinoyStackOverflower Jul 06 '20 at 02:26

1 Answers1

2

array_unique() is simply a reduce operation. What you want is a slightly more complex one so use array_reduce()

$exclude = array_flip(['qty']); // list of properties to exclude when creating a hash

$totals = array_reduce($arr, function($totals, $item) use ($exclude) {
    $id = array_diff_key($item, $exclude);
    ksort($id); // sort by key to always get the same order
    $hash = crc32(json_encode($id));
    if (array_key_exists($hash, $totals)) {
        $totals[$hash]['qty'] += $item['qty'];
    } else {
        $totals[$hash] = $item;
    }
    return $totals;
}, []);

This builds up a new array keyed by a hash of identifying values (everything except for qty) that, upon finding an entry it already knows about, increases the qty.

I've gone with a CRC32 hash of the JSON encoded string for speed. You can use just about any hashing / serialization combo though.

Demo ~ https://3v4l.org/YDsfc

Special nods to the following posts:

Phil
  • 157,677
  • 23
  • 242
  • 245
  • thanks for, but I tried adding a different value in the `special_instructions` but it combined it with the others that doesnt have a `special_instructions` value. This is before it ran through your code: https://pastebin.com/hG8C35Q0 noticed that the other has a value in `special_instructions`, this is AFTER your code: https://pastebin.com/sCu76Que Ideal output should be like this: https://pastebin.com/Gk5ttWEr – PinoyStackOverflower Jul 06 '20 at 02:33