Search code examples
phpmultidimensional-arrayconcatenationgroupingarray-sum

Group rows of data and in each group sum one column and concatenate another column


In php, I have an indexed array of associative rows like this:

$the_array = [
   ['id' => 1, 'value' => 10, 'name' => 'apple'],
   ['id' => 1, 'value' => 20, 'name' => 'orange'],
   ['id' => 1, 'value' => 30, 'name' => 'banana'],
   ['id' => 2, 'value' => 100, 'name' => 'car'], 
   ['id' => 2, 'value' => 200, 'name' => 'bicycle'],
];

and I would like to restructure it to by grouping on id values and in each group I'd like to sum the value values and make a comma-separated string of the name values.

[
    ['id' => 1, 'value' => 60,  'name' => 'apple,orange,banana'],
    ['id' => 2, 'value' => 300, 'name' => 'car,bicycle']
]

This is what I tried:

function group_by($key, $data) {
    $result = array();
    foreach($data as $val) {
        if(array_key_exists($key, $val)){
            $result[$val[$key]][] = $val;
        }else{
            $result[""][] = $val;
        }
    }
    return $result;
}

It's not working and the result is wrong/incomplete.


Solution

  • I would create an intermediary array which groups into array keys by id first, then use that to call combinations of array_column() with array_sum() and implode() to produce your sum value and combined name string.

    $temp_array = [];
    foreach ($the_array as $init) {
      // Initially, group them on the id key as sub-arrays
      $temp_array[$init['id']][] = $init;
    }
    
    $result = [];
    foreach ($temp_array as $id => $arr) {
      // Loop once for each id ($temp_array has 2 elements from your sample)
      // And add an element to $result
      $result[] = [
        'id' => $id,
        // Sum the value subkeys
        // array_column() returns just the key 'value' as an array
        // array_sum() adds them
        'value' => array_sum(array_column($arr, 'value')),
        // implode the name subkeys into a string
        'name' => implode(',', array_column($arr, 'name'))
      ];
    }
    
    print_r($result);
    Array
    (
        [0] => Array
            (
                [id] => 1
                [value] => 60
                [name] => apple,orange,banana
            )
    
        [1] => Array
            (
                [id] => 2
                [value] => 300
                [name] => car,bicycle
            )
    
    )