[php] How to sum all column values in multi-dimensional array?

How can I add all the columnar values by associative key? Note that key sets are dynamic.

Input array:

Array
(
    [0] => Array
        (
            [gozhi] => 2
            [uzorong] => 1
            [ngangla] => 4
            [langthel] => 5
        )

    [1] => Array
        (
            [gozhi] => 5
            [uzorong] => 0
            [ngangla] => 3
            [langthel] => 2
        )

    [2] => Array
        (
            [gozhi] => 3
            [uzorong] => 0
            [ngangla] => 1
            [langthel] => 3
        )
)

Desired result:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

This question is related to php arrays multidimensional-array sum

The answer is


Go through each item of the array and sum values to previous values if they exist, if not just assign the value.

<?php
$array = 
[
    [
        'a'=>1,
        'b'=>1,
        'c'=>1,
    ],
    [
        'a'=>2,
        'b'=>2,
    ],
    [
        'a'=>3,
        'd'=>3,
    ]
];

$result = array_reduce($array, function($carry, $item) {
    foreach($item as $k => $v)
        $carry[$k] = $v + ($carry[$k] ?? 0);

    return $carry;
}, []);

print_r($result);

Output:

Array
(
    [a] => 6
    [b] => 3
    [c] => 1
    [d] => 3
)

Or just loop through each sub array, and group the values for each column. Eventually summing them:

foreach($array as $subarray)
    foreach($subarray as $key => $value)
        $grouped[$key][] = $value;

$sums = array_map('array_sum', $grouped);

You can use array_walk_recursive() to get a general-case solution for your problem (the one when each inner array can possibly have unique keys).

$final = array();

array_walk_recursive($input, function($item, $key) use (&$final){
    $final[$key] = isset($final[$key]) ?  $item + $final[$key] : $item;
});

Example with array_walk_recursive() for the general case

Also, since PHP 5.5 you can use the array_column() function to achieve the result you want for the exact key, [gozhi], for example :

array_sum(array_column($input, 'gozhi')); 

Example with array_column() for the specified key

If you want to get the total sum of all inner arrays with the same keys (the desired result that you've posted), you can do something like this (bearing in mind that the first inner array must have the same structure as the others) :

$final = array_shift($input);

foreach ($final as $key => &$value){
   $value += array_sum(array_column($input, $key));
}    

unset($value);

Example with array_column() in case all inner arrays have the same keys

If you want a general-case solution using array_column() then at first you may consider to get all unique keys , and then get the sum for each key :

$final = array();

foreach($input as $value)
    $final = array_merge($final, $value);

foreach($final as $key => &$value)
    $value = array_sum(array_column($input, $key));

unset($value);

Example with array_column() for the general case


Here you have how I usually do this kind of operations.

// We declare an empty array in wich we will store the results
$sumArray = array();

// We loop through all the key-value pairs in $myArray
foreach ($myArray as $k=>$subArray) {

   // Each value is an array, we loop through it
   foreach ($subArray as $id=>$value) {

       // If $sumArray has not $id as key we initialize it to zero  
       if(!isset($sumArray[$id])){
           $sumArray[$id] = 0;
       }

       // If the array already has a key named $id, we increment its value
       $sumArray[$id]+=$value;
    }
 }

 print_r($sumArray);

Here's a version where the array keys may not be the same for both arrays, but you want them all to be there in the final array.

function array_add_by_key( $array1, $array2 ) {
    foreach ( $array2 as $k => $a ) {
        if ( array_key_exists( $k, $array1 ) ) {
            $array1[$k] += $a;
        } else {
            $array1[$k] = $a;
        }
    }
    return $array1;
}

It can also be done using array_walk:

function array_sum_values(array $input, $key) {
   $sum = 0;
   array_walk($input, function($item, $index, $params) {
         if (!empty($item[$params[1]]))
            $params[0] += $item[$params[1]];
      }, array(&$sum, $key)
   );
   return $sum;
}

var_dump(array_sum_values($arr, 'gozhi'));

Not so readable like previous solutions but it works :)


For those who landed here and are searching for a solution that merges N arrays AND also sums the values of identical keys found in the N arrays, I've written this function that works recursively as well. (See: https://gist.github.com/Nickology/f700e319cbafab5eaedc)

Example:

$a = array( "A" => "bob", "sum" => 10, "C" => array("x","y","z" => 50) );
$b = array( "A" => "max", "sum" => 12, "C" => array("x","y","z" => 45) );
$c = array( "A" => "tom", "sum" =>  8, "C" => array("x","y","z" => 50, "w" => 1) );

print_r(array_merge_recursive_numeric($a,$b,$c));

Will result in:

Array
(
    [A] => tom
    [sum] => 30
    [C] => Array
        (
            [0] => x
            [1] => y
            [z] => 145
            [w] => 1
        )

)

Here's the code:

<?php 
/**
 * array_merge_recursive_numeric function.  Merges N arrays into one array AND sums the values of identical keys.
 * WARNING: If keys have values of different types, the latter values replace the previous ones.
 * 
 * Source: https://gist.github.com/Nickology/f700e319cbafab5eaedc
 * @params N arrays (all parameters must be arrays)
 * @author Nick Jouannem <[email protected]>
 * @access public
 * @return void
 */
function array_merge_recursive_numeric() {

    // Gather all arrays
    $arrays = func_get_args();

    // If there's only one array, it's already merged
    if (count($arrays)==1) {
        return $arrays[0];
    }

    // Remove any items in $arrays that are NOT arrays
    foreach($arrays as $key => $array) {
        if (!is_array($array)) {
            unset($arrays[$key]);
        }
    }

    // We start by setting the first array as our final array.
    // We will merge all other arrays with this one.
    $final = array_shift($arrays);

    foreach($arrays as $b) {

        foreach($final as $key => $value) {

            // If $key does not exist in $b, then it is unique and can be safely merged
            if (!isset($b[$key])) {

                $final[$key] = $value;

            } else {

                // If $key is present in $b, then we need to merge and sum numeric values in both
                if ( is_numeric($value) && is_numeric($b[$key]) ) {
                    // If both values for these keys are numeric, we sum them
                    $final[$key] = $value + $b[$key];
                } else if (is_array($value) && is_array($b[$key])) {
                    // If both values are arrays, we recursively call ourself
                    $final[$key] = array_merge_recursive_numeric($value, $b[$key]);
                } else {
                    // If both keys exist but differ in type, then we cannot merge them.
                    // In this scenario, we will $b's value for $key is used
                    $final[$key] = $b[$key];
                }

            }

        }

        // Finally, we need to merge any keys that exist only in $b
        foreach($b as $key => $value) {
            if (!isset($final[$key])) {
                $final[$key] = $value;
            }
        }

    }

    return $final;

}

?>

this works great on my laravel project

print_r($Array); // your original array

$_SUM = [];

// count($Array[0]) => if the number of keys are equall in all arrays then do a count of index 0 etc.
for ($i=0; $i < count($Array[0]); $i++) {
    $_SUM[] = $Array[0][$i] + $Array[1][$i]; // do a for loop on the count 
}

print_r($_SUM); // get a sumed up array

example array here

Code here:

        $temp_arr = [];
        foreach ($a as $k => $v) {
            if(!is_null($v)) {
                $sum = isset($temp_arr[$v[0]]) ? ((int)$v[5] + $sum) : (int)$v[5];
                $temp_arr[$v[0]] = $sum;
            }
        }
        return $temp_arr;

Result:

{SEQ_OK: 1328,SEQ_ERROR: 561}

$sumArray = array();

foreach ($myArray as $k=>$subArray) {
  foreach ($subArray as $id=>$value) {
    if(!isset($sumArray[$id])){
     $sumArray[$id] =$value;
    }else {
     $sumArray[$id]+=$value;
    }
  }
}

print_r($sumArray);

`

For example, you can pluck all fields from a result like this below.

I am picking out the 'balance' from an array and save to a variable

$kii =   $user->pluck('balance');

then on the next line u can sum like this:

$sum =  $kii->sum(); 

Hope it helps.


Another version, with some benefits below.

$sum = ArrayHelper::copyKeys($arr[0]);

foreach ($arr as $item) {
    ArrayHelper::addArrays($sum, $item);
}


class ArrayHelper {

    public function addArrays(Array &$to, Array $from) {
        foreach ($from as $key=>$value) {
            $to[$key] += $value;
        }
    }

    public function copyKeys(Array $from, $init=0) {
        return array_fill_keys(array_keys($from), $init);
    }

}

I wanted to combine the best of Gumbo's, Graviton's, and Chris J's answer with the following goals so I could use this in my app:

a) Initialize the 'sum' array keys outside of the loop (Gumbo). Should help with performance on very large arrays (not tested yet!). Eliminates notices.

b) Main logic is easy to understand without hitting the manuals. (Graviton, Chris J).

c) Solve the more general problem of adding the values of any two arrays with the same keys and make it less dependent on the sub-array structure.

Unlike Gumbo's solution, you could reuse this in cases where the values are not in sub arrays. Imagine in the example below that $arr1 and $arr2 are not hard-coded, but are being returned as the result of calling a function inside a loop.

$arr1 = array(
    'gozhi' => 2,
    'uzorong' => 1,
    'ngangla' => 4,
    'langthel' => 5
);

$arr2 = array(
   'gozhi' => 5,
   'uzorong' => 0,
   'ngangla' => 3,
   'langthel' => 2
);

$sum = ArrayHelper::copyKeys($arr1);

ArrayHelper::addArrays($sum, $arr1);
ArrayHelper::addArrays($sum, $arr2);

We need to check first if array key does exist.

CODE:

$sum = array();
foreach ($array as $key => $sub_array) {
    foreach ($sub_array as $sub_key => $value) {

        //If array key doesn't exists then create and initize first before we add a value.
        //Without this we will have an Undefined index error.
        if( ! array_key_exists($sub_key, $sum)) $sum[$sub_key] = 0;

        //Add Value
        $sum[$sub_key]+=$value;
    }
}
print_r($sum);

OUTPUT With Array Key Validation:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

OUTPUT Without Array Key Validation:

Notice: Undefined index: gozhi in F:\web\index.php on line 37

Notice: Undefined index: uzorong in F:\web\index.php on line 37

Notice: Undefined index: ngangla in F:\web\index.php on line 37

Notice: Undefined index: langthel in F:\web\index.php on line 37

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)

This is a bad practice although it prints the output. Always check first if key does exist.


You can try this:

$c = array_map(function () {
      return array_sum(func_get_args());
     },$a, $b);

and finally:

print_r($c);

Use this snippet:

$key = 'gozhi';
$sum = array_sum(array_column($array,$key));

Here is a solution similar to the two others:

$acc = array_shift($arr);
foreach ($arr as $val) {
    foreach ($val as $key => $val) {
        $acc[$key] += $val;
    }
}

But this doesn’t need to check if the array keys already exist and doesn’t throw notices neither.


$sumArray = array();
foreach ($myArray as $k => $subArray) {
    foreach ($subArray as $id => $value) {
        if (!isset($sumArray[$id])) {
            $sumArray[$id] = 0;
        }
        $sumArray[$id]+=$value;
    }
}

$newarr=array();
foreach($arrs as $value)
{
  foreach($value as $key=>$secondValue)
   {
       if(!isset($newarr[$key]))
        {
           $newarr[$key]=0;
        }
       $newarr[$key]+=$secondValue;
   }
}

It can also be done using array_map :

$rArray = array(
    0 => array(
        'gozhi' => 2,
        'uzorong' => 1,
        'ngangla' => 4,
        'langthel' => 5
    ),
    1 => array(
        'gozhi' => 5,
        'uzorong' => 0,
        'ngangla' => 3,
        'langthel' => 2
    ),
    2 => array(
        'gozhi' => 3,
        'uzorong' => 0,
        'ngangla' => 1,
        'langthel' => 3
    ),
);

$sumResult = call_user_func_array('array_map', array_merge(['sum'], $rArray));

function sum()
{
    return array_sum(func_get_args());
}

Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to multidimensional-array

what does numpy ndarray shape do? len() of a numpy array in python What is the purpose of meshgrid in Python / NumPy? Convert a numpy.ndarray to string(or bytes) and convert it back to numpy.ndarray Typescript - multidimensional array initialization How to get every first element in 2 dimensional list How does numpy.newaxis work and when to use it? How to count the occurrence of certain item in an ndarray? Iterate through 2 dimensional array Selecting specific rows and columns from NumPy array

Examples related to sum

Iterating over arrays in Python 3 Get total of Pandas column Pandas: sum DataFrame rows for given columns How to find sum of several integers input by user using do/while, While statement or For statement SQL Sum Multiple rows into one Python Pandas counting and summing specific conditions SELECT query with CASE condition and SUM() Using SUMIFS with multiple AND OR conditions How to SUM parts of a column which have same text value in different column in the same row how to count the total number of lines in a text file using python