Search code examples
phpmultidimensional-arraygroupingarray-mergearray-sum

PHP - How To Grouping if value same in array


This my array example

Array
(
  [0] => Array ( [_id] => 5f76b1788ee23077dccd1a2c [product] => Array ( [0] => Array ( [_id] => 5d0391a4a72ffe76b8fcc610 ) ) [count] => 1 )
  [1] => Array ( [_id] => 5f76b6288ee2300700cd1a3a [product] => Array ( [0] => Array ( [_id] => 5d0391b6a72ffe76b8fcc611 ) ) [count] => 1 )
  [2] => Array ( [_id] => 5f76d2488ee23083d3cd1a4a [product] => Array ( [0] => Array ( [_id] => 5d0391b6a72ffe76b8fcc611 ) ) [count] => 1) 
)

And i want to group if product value same, like this,

Array
(
  [0] => Array ( [_id] => 5f76b1788ee23077dccd1a2c [product] => Array ( [0] => Array ( [_id] => 5d0391a4a72ffe76b8fcc610 ) ) [count] => 1 )
  [1] => Array ( [_id] => 5f76b6288ee2300700cd1a3a [product] => Array ( [0] => Array ( [_id] => 5d0391b6a72ffe76b8fcc611 ) ) [count] => 2 )
)

Solution

  • It makes no sense to retain the first level ids since you are arbitrarily trashing some of the first level ids (damaging the relationships) during the merging process.

    Instead I recommend that you only isolate the data that is accurately related.

    If this output does not serve your needs, then I'll ask for further question clarification.

    By assigning temporary keys to your output array, the output array also acts as a lookup array by which you can swiftly check for uniqueness. The "null coalescing operator" (??) sets a fallback value of 0 when an id is encountered for the first time -- this prevents generating any warnings regarding undeclared keys.

    Code: (Demo)

    $array = [
        ['_id' => '5f76b1788ee23077dccd1a2c', 'product' => ['_id'=>'5d0391a4a72ffe76b8fcc610'], 'count'=> 1],
        ['_id' => '5f76b6288ee2300700cd1a3a', 'product' => ['_id'=>'5d0391b6a72ffe76b8fcc611'], 'count'=> 1],
        ['_id' => '5f76d2488ee23083d3cd1a4a', 'product' => ['_id'=>'5d0391b6a72ffe76b8fcc611'], 'count'=> 1]
    ];
    
    $productCounts = [];
    foreach ($array as $item) {
        $productId = $item['product']['_id'];
        $productCounts[$productId] = ($productCounts[$productId] ?? 0) + $item['count'];
    }
    
    var_export($productCounts);
    

    Output:

    array (
      '5d0391a4a72ffe76b8fcc610' => 1,
      '5d0391b6a72ffe76b8fcc611' => 2,
    )
    

    If you insist of the desired output in your question, then it can be as simple and efficient as this...

    Code: (Demo)

    $result = [];
    foreach ($array as $item) {
        $productId = $item['product']['_id'];
        if (!isset($result[$productId])) {
            $result[$productId] = $item;
        } else {
            $result[$productId]['count'] += $item['count'];
        }
    }
    
    var_export(array_values($result));
    

    Output:

    array (
      0 => 
      array (
        '_id' => '5f76b1788ee23077dccd1a2c',
        'product' => 
        array (
          '_id' => '5d0391a4a72ffe76b8fcc610',
        ),
        'count' => 1,
      ),
      1 => 
      array (
        '_id' => '5f76b6288ee2300700cd1a3a',
        'product' => 
        array (
          '_id' => '5d0391b6a72ffe76b8fcc611',
        ),
        'count' => 2,
      ),
    )