¿Cómo sumar todos los valores de columna en una matriz multidimensional?


116

¿Cómo puedo agregar todos los valores de columnas por clave asociativa? Tenga en cuenta que los conjuntos de teclas son dinámicos.

Matriz de entrada:

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

Resultado deseado:

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

Para una situación común, dos matrices multidimensionales no tienen exactamente las mismas claves. fusionar / sumar matriz multidimensional php
Kris Roofe

Respuestas:


92
$sumArray = array();

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

print_r($sumArray);

49
Eso arrojará avisos para la primera iteración ya que las claves aún no existen.
Gumbo

¿Si hay n matrices?
Muhammad Usman

2
@RanaMuhammadUsman: Si hay nmatrices, use esta solución .
Amal Murali

2
array_reduce me suena más bonito stackoverflow.com/questions/14195916/…
Bill'o

13
Para evitar los avisos, puede reemplazar la línea que asigna los valores a $ sumArray a: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ valor: $ sumArray [$ id] = $ valor;
Dave O'Brien

185

Puede usar array_walk_recursive()para obtener una solución de caso general para su problema ( aquella en la que cada matriz interna puede tener claves únicas ).

$final = array();

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

Ejemplo con array_walk_recursive()para el caso general

Además, dado que PHP 5.5 se puede utilizar la array_column()función de lograr el resultado deseado para la clave exacta , [gozhi]por ejemplo:

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

Ejemplo con array_column()para la clave especificada

Si desea obtener la suma total de todas las matrices internas con las mismas claves ( el resultado deseado que ha publicado ), puede hacer algo como esto ( teniendo en cuenta que la primera matriz interna debe tener la misma estructura que las demás ):

$final = array_shift($input);

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

unset($value);

Ejemplo con array_column()en caso de que todas las matrices internas tengan las mismas claves

Si desea utilizar una solución de caso general, array_column()al principio puede considerar obtener todas las claves únicas y luego obtener la suma de cada clave:

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

Ejemplo con array_column()para el caso general


31

Utilice este fragmento:

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

He editado la pregunta para aclarar que esta solución está algo poco hecha en términos de entregar el resultado deseado del OP. Dicho esto, si expande su respuesta, es muy probable que se convierta en un duplicado de las respuestas publicadas anteriormente.
mickmackusa

28

Aquí hay una solución similar a las otras dos:

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

Pero esto no necesita verificar si las claves de la matriz ya existen y tampoco arroja avisos.


+1 solución muy inteligente para esta estructura de matriz específica. Lástima que no funcione en el caso más general de matrices estructuradas como el resultado final.
Todd Chaffee

22

También se puede hacer usando 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());
}

1
Perfecto para n números de matriz
Dushyant Joshi

1
¿Cómo cambiaría esto para N números de matriz?
Pathros

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

3
Tenga en cuenta que esto le dará avisos de PHP (índice indefinido) cada vez que acceda a $ newarr [$ key] en el lado derecho de su asignación, cuando dichos valores aún no existen.
Anti Veeranna

Creo que agregué un cheque para inicializar el $ newarr [$ key]
Graviton

4
POR FAVOR, deje comentarios si rechaza a alguien ... No hay forma de mejorar la solución si no deja comentarios.
Todd Chaffee

@Graviton No voté negativamente, pero diré que cada respuesta de StackOverflow debe incluir alguna explicación sobre cómo funciona la solución y / o por qué es recomendable. Recuerde que cada página de este sitio / red es un recurso educativo para miles y miles de desarrolladores con una amplia gama de habilidades / conocimientos. (Si votara negativamente cada vez que encontraba una respuesta de solo código, me
quedaría sin

5

Otra versión, con algunos beneficios a continuación.

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

}

Quería combinar lo mejor de la respuesta de Gumbo, Graviton y Chris J con los siguientes objetivos para poder usar esto en mi aplicación:

a) Inicialice las claves de matriz 'suma' fuera del bucle (Gumbo). Debería ayudar con el rendimiento en matrices muy grandes (¡aún no probado!). Elimina avisos.

b) La lógica principal es fácil de entender sin tener que tocar los manuales. (Graviton, Chris J).

c) Resuelva el problema más general de sumar los valores de dos arreglos cualesquiera con las mismas claves y hacerlo menos dependiente de la estructura del subarreglo.

A diferencia de la solución de Gumbo, puede reutilizar esto en los casos en que los valores no estén en submatrices. Imagínese en el ejemplo siguiente que $arr1y $arr2no están codificados, pero se devuelven como resultado de llamar a una función dentro de un bucle.

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

4

También se puede hacer usando 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'));

No es tan legible como las soluciones anteriores pero funciona :)


3

Aquí hay una versión en la que las claves de la matriz pueden no ser las mismas para ambas matrices, pero desea que todas estén allí en la matriz final.

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

3

Primero debemos verificar si existe una clave de matriz.

CÓDIGO:

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

SALIDA con validación de clave de matriz:

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

SALIDA sin validación de clave de matriz:

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
)

Esta es una mala práctica aunque imprime la salida. Siempre verifique primero si la clave existe.


1

Para aquellos que aterrizaron aquí y están buscando una solución que combine N matrices Y también sume los valores de claves idénticas que se encuentran en las N matrices, escribí esta función que también funciona de forma recursiva. (Ver: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

Ejemplo:

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

Resultará en:

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

)

Aquí está el código:

<?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 <nick@nickology.com>
 * @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;

}

?>

1

Revise cada elemento de la matriz y sume los valores a los valores anteriores si existen, si no, simplemente asigne el valor.

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

Salida:

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

O simplemente recorra cada submatriz y agrupe los valores de cada columna. Finalmente resumiéndolos:

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

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

0

Aquí tienes cómo suelo hacer este tipo de operaciones.

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

¿Podría dar una explicación de este código y por qué responde a la pregunta? Será más útil que descargar solo un bloque de código sin ninguna explicación.
trincot

¡¡por supuesto!! Lo siento, soy español y para mí, ¡explicar que el código es lo más difícil cuando respondo una pregunta! Gracias por tu consejo @trincot
Luis González

0

Puedes probar esto:

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

y finalmente:

print_r($c);

1
¿Para qué estás usando exactamente $ay $bcuándo llamas array_map()? Mejore esta respuesta de solo código.
mickmackusa

0

esto funciona muy bien en mi proyecto laravel

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

Si bien esto puede funcionar para su proyecto Laravel, esta no es una solución buena / viable para ESTA pregunta.
mickmackusa

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

Este es un duplicado de una respuesta de MUCHOS años antes. stackoverflow.com/a/1496697/2943403 Lea todas las respuestas existentes antes de publicar las suyas para que no haya redundancias en la misma página.
mickmackusa

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

`

Por favor revise Cómo escribo una buena respuesta . Las respuestas de solo código no se recomiendan porque no explican cómo resuelven el problema en la pregunta. Debe actualizar su respuesta para explicar qué hace esto y cómo mejora las muchas respuestas con votos positivos que ya tiene esta pregunta de 8 años.
FluffyKitten

Básicamente, un duplicado de una respuesta anterior: stackoverflow.com/a/20532196/2943403
mickmackusa

-2

Por ejemplo, puede extraer todos los campos de un resultado como este a continuación.

Estoy seleccionando el 'saldo' de una matriz y lo guardo en una variable

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

luego en la siguiente línea puedes sumar así:

$sum =  $kii->sum(); 

Espero eso ayude.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.