Ahmed Youssef
Ahmed Youssef

Reputation: 259

Group row data of a 2d array by one column and sum another column within each group

I need to sum the column data of rows after grouping by another column.

Example input:

[
    ['id' => 1, 'name' => 'John00', 'value' => 0.4],
    ['id' => 2, 'name' => 'Ann01', 'value' => 0.001],
    ['id' => 1, 'name' => 'John00', 'value' => 0.2],
    ['id' => 3, 'name' => 'Ann', 'value' => 0.1],
    ['id' => 2, 'name' => 'Ann01', 'value' => 0.01],
    ['id' => 1, 'name' => 'John00', 'value' => 0.3],
]

How can I consolidate rows with the same id and sum the value values in each group to return an indexed array of associative arrays?

Desired result:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => John00
            [value] => 0.9
        )

    [1] => Array
        (
            [id] => 2
            [name] => Ann01
            [value] => 0.011
        )

    [2] => Array
        (
            [id] => 3
            [name] => Ann
            [value] => 0.1
        )
)

Upvotes: -1

Views: 972

Answers (4)

Tom Haigh
Tom Haigh

Reputation: 57815

I'm not completely sure what you are trying to do - I assume you want the sum grouped by the id for each distinct id to populate a flat associative array, but I may be wrong.

$sums = array();

foreach ($source as $ar) {
    //create an entry for this id in the array of sums if does not exist.
    if (!isset($sums[ $ar['id'] ])) {
        $sums[ $ar['id'] ] = 0;
    }
    
    //add 'value' key to sum for that id
    $sums[ $ar['id'] ] += $ar['value'];
}

//sort by id
ksort($sums);

print_r($sums);

Output:

Array
(
    [1] => 0.9
    [2] => 0.011
    [3] => 0.1
)

Upvotes: 2

soulmerge
soulmerge

Reputation: 75704

This looks like it's coming from a database, and the query is the best place to do such things. (if this is not data from a db, just ignore this answer).

SELECT id, MAX(name), SUM(value)
FROM YourTable
-- add your WHERE-constraints here
GROUP BY id;

Upvotes: 0

mickmackusa
mickmackusa

Reputation: 47894

To ensure that the result array has the same structure of the input array (an indexed array of associative rows) -- just reducing the total row count in the process -- push the whole as a reference variable into the result array whenever a unique id value is encountered. If a row is encountered where the id has been encountered before, only add the current value value to the value value in the reference.

Code: (Demo)

$result = [];
foreach ($array as $row) {
    if (!isset($ref[$row['id']])) {
        $ref[$row['id']] = $row;
        $result[] =& $ref[$row['id']];
        continue;
    }
    $ref[$row['id']]['value'] += $row['value'];
}
print_r($result);

Upvotes: 0

pauljwilliams
pauljwilliams

Reputation: 19225

Pseduo-code:

$totals = array();

function add($in)
{
   global $totals;
   if(!isset($totals($in['id']))
   {
      $totals[$in['id']] = $in['value'];
   }else
   {
      $totals[$in['id']] += $in['value'];
   }
}

array_walk('add',$input_array);

var_dump($totals);

Upvotes: -1

Related Questions