marknt15
marknt15

Reputation: 5127

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
)

Upvotes: 150

Views: 306912

Answers (18)

Chris J
Chris J

Reputation: 7779

$sumArray = array();

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

print_r($sumArray);

Upvotes: 102

DMat
DMat

Reputation: 144

Simple example with array_reduce()

$numbers = [10,20,30];

$total = 0;

foreach ($numbers as $number) {
    $total += $number;
}

echo $total; // 60

=>

$numbers = [10,20,30];

$total  = array_reduce($numbers, function ($previous, $current) {
    return $previous + $current;
});

echo $total; // 60

With assoc array:

$carts = [
    ['item' => 'A', 'qty' => 2, 'price' => 10],
    ['item' => 'B', 'qty' => 3, 'price' => 20],
    ['item' => 'C', 'qty' => 5, 'price' => 30]
];


$total = array_reduce(
    $carts,
    function ($prev, $item) {
        return $prev + $item['qty'] * $item['price'];
    }
);

echo $total; // 155

More info => https://www.phptutorial.net/php-tutorial/php-array_reduce/

Upvotes: 2

user1765774
user1765774

Reputation: 1

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}

Upvotes: -1

Progrock
Progrock

Reputation: 7485

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);

Upvotes: 4

Emmanuel Iyen
Emmanuel Iyen

Reputation: 447

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.

Upvotes: -1

Tan Ory Jaka Perdana
Tan Ory Jaka Perdana

Reputation: 917

Use this snippet:

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

Upvotes: 71

JJJJ
JJJJ

Reputation: 1358

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.

Upvotes: 3

npcoda
npcoda

Reputation: 475

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());
}

Upvotes: 22

Channeth Khon
Channeth Khon

Reputation: 13

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

Upvotes: -1

1990rk4
1990rk4

Reputation: 768

You can try this:

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

and finally:

print_r($c);

Upvotes: -1

Luis Gonz&#225;lez
Luis Gonz&#225;lez

Reputation: 3589

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);

Upvotes: 1

Nick
Nick

Reputation: 2613

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;

}

?>

Upvotes: 1

potashin
potashin

Reputation: 44601

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

Upvotes: 232

Filip G&#243;rczyński
Filip G&#243;rczyński

Reputation: 765

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 :)

Upvotes: 4

Bollis
Bollis

Reputation: 385

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;
}

Upvotes: 3

Todd Chaffee
Todd Chaffee

Reputation: 6824

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);

Upvotes: 5

Gumbo
Gumbo

Reputation: 655795

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.

Upvotes: 28

Graviton
Graviton

Reputation: 83316

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

Upvotes: 13

Related Questions