Search code examples
phparraysmultidimensional-arraysumgrouping

Group rows of a 2d array by one column and sum another column within the group


Given this array:

array(40) {
  [0]=>
  array(10) {
    ["item"]=>
    string(5) "AABBCC"
    ["quants"]=>
    string(1) "1"
  }
  [1]=>
  array(10) {
    ["item"]=>
    string(5) "AABBCC"
    ["quants"]=>
    string(1) "1"
  }  
  [2]=>
  array(10) {
    ["item"]=>
    string(5) "SLF02"
    ["quants"]=>
    string(1) "1"

  }
  [3]=>
  array(10) {
    ["item"]=>
    string(5) "SLF02"
    ["quants"]=>
    string(1) "3"
  }
}

how without using a foreach do I end up with this output:

  array(40) {
    [0]=>
    array(10) {
      ["item"]=>
      string(5) "AABBCC"
      ["quants"]=>
      string(1) "2"
    }
    [1]=>
    array(10) {
      ["item"]=>
      string(5) "SLF02"
      ["quants"]=>
      string(1) "3"
    }  
  }

Are there any array_sum() functions to do this with a multidimensional array?


Solution

  • This is a bad idea, but seemed like a fun challenge to do without a foreach:

      $arr = 
    [
      [
        "item" =>"AABBCC",
        "quants" => "1",
      ],
      [
        "item" => "AABBCC", 
        "quants" => "1",
      ],
      [
        "item" => "SLF02", 
        "quants" => "1",
      ],
      [
        "item" => "SLF02", 
        "quants" => "3",
      ]
    ];
    
    $arr = array_values(call_user_func_array("array_merge", array_map(function($i) use ($arr) {
      return [$i["item"] => ["item" => $i["item"], "quants" => array_reduce(
        array_filter($arr, function($j) use ($i) {
            return $j["item"] == $i["item"]; 
        }), function($carry, $item) { 
            return $carry + $item["quants"]; 
        })
      ]];
    }, $arr)));
    
    var_dump($arr);
    
    /*
    array(2) {
      [0]=>
      array(2) {
        ["item"]=>
        string(6) "AABBCC"
        ["quants"]=>
        int(2)
      }
      [1]=>
      array(2) {
        ["item"]=>
        string(5) "SLF02"
        ["quants"]=>
        int(4)
      }
    }
    */