Como somar todos os valores da coluna em uma matriz multidimensional?


116

Como posso adicionar todos os valores colunares por chave associativa? Observe que os conjuntos de chaves são 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 desejado:

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

Para uma situação comum, duas matrizes multidimensionais não têm exatamente as mesmas chaves. mesclar / somar array multi
dimensional

Respostas:


92
$sumArray = array();

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

print_r($sumArray);

49
Isso lançará avisos para a primeira iteração, pois as chaves ainda não existem.
Gumbo

Se houver n matrizes?
Muhammad Usman de

2
@RanaMuhammadUsman: Se houver narrays, use esta solução .
Amal Murali

2
array_reduce soa mais bonito para mim stackoverflow.com/questions/14195916/…
Bill'o

13
Para evitar os avisos, você pode substituir a linha atribuindo os valores ao $ sumArray para: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ valor: $ sumArray [$ id] = $ valor;
Dave O'Brien

185

Você pode usar array_walk_recursive() para obter uma solução de caso geral para o seu problema ( aquela em que cada array interno pode ter chaves exclusivas ).

$final = array();

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

Exemplo com array_walk_recursive()para o caso geral

Além disso, como PHP 5.5 você pode usar a array_column()função para alcançar o resultado desejado para a chave exata , [gozhi]por exemplo:

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

Exemplo com array_column()para a chave especificada

Se você deseja obter a soma total de todos os arrays internos com as mesmas chaves ( o resultado desejado que postou ), você pode fazer algo assim ( tendo em mente que o primeiro array interno deve ter a mesma estrutura que os outros ):

$final = array_shift($input);

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

unset($value);

Exemplo com array_column()caso todos os arrays internos tenham as mesmas chaves

Se você deseja uma solução de caso geral usando array_column()então, primeiro você pode considerar obter todas as chaves exclusivas e, em seguida, obter a soma de cada chave:

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

Exemplo com array_column()para o caso geral


31

Use este snippet:

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

Eu editei a pergunta para esclarecer que esta solução está um tanto mal cozida em termos de entregar o resultado desejado do OP. Dito isso, se você expandir sua resposta, muito provavelmente ela se tornará uma duplicata das respostas postadas anteriormente.
mickmackusa

28

Aqui está uma solução semelhante às duas outras:

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

Mas isso não precisa verificar se as chaves do array já existem e também não lança avisos.


1 solução muito inteligente para esta estrutura de array específica. Uma pena que não funciona no caso mais geral de arrays todos estruturados como o resultado final.
Todd Chaffee

22

Também pode ser feito 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
Perfeito para n números da matriz
Dushyant Joshi

1
Como você mudaria isso para N números da 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
Note que isto lhe dará avisos PHP (índice indefinido) toda vez que você acessar $ newarr [$ key] no lado direito de sua atribuição, quando tais valores ainda não existem.
Anti Veeranna

Acho que adicionei um cheque para inicializar a $ newarr [$ key]
Graviton

4
POR FAVOR, deixe comentários se você votar em alguém ... Não há como melhorar a solução se você não deixar comentários.
Todd Chaffee de

@Graviton Eu não fiz downvote, mas direi que cada resposta StackOverflow deve incluir alguma explicação de como a solução funciona e / ou por que é aconselhável. Lembre-se de que cada página neste site / rede é um recurso educacional para milhares e milhares de desenvolvedores com uma ampla gama de habilidades / conhecimentos. (Se eu fizesse uma votação negativa toda vez que encontrasse uma resposta apenas de código, ficaria sem pontos de rep.)
mickmackusa

5

Outra versão, com alguns benefícios abaixo.

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

}

Eu queria combinar o melhor da resposta de Gumbo, Graviton e Chris J com os seguintes objetivos para poder usar isso em meu aplicativo:

a) Inicialize as chaves do array 'sum' fora do loop (Gumbo). Deve ajudar no desempenho em arrays muito grandes (ainda não testado!). Elimina avisos.

b) A lógica principal é fácil de entender sem bater nos manuais. (Graviton, Chris J).

c) Resolva o problema mais geral de adicionar os valores de quaisquer dois arrays com as mesmas chaves e torná-lo menos dependente da estrutura do submatriz.

Ao contrário da solução de Gumbo, você pode reutilizar isso nos casos em que os valores não estão em submatrizes. Imagine no exemplo abaixo que $arr1e $arr2não estão embutidos no código, mas estão sendo retornados como resultado da chamada de uma função dentro de um 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);

4

Também pode ser feito 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'));

Não é tão legível como as soluções anteriores, mas funciona :)


3

Aqui está uma versão em que as chaves do array podem não ser as mesmas para os dois arrays, mas você deseja que todos eles estejam lá no array 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

Precisamos verificar primeiro se a chave do array existe.

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

OUTPUT com validação de chave de matriz:

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

OUTPUT sem validação de chave de array:

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 é uma prática ruim, embora imprima a saída. Sempre verifique primeiro se a chave existe.


1

Para aqueles que chegaram aqui e estão procurando por uma solução que combine N arrays E também some os valores de chaves idênticas encontradas nos N arrays, escrevi esta função que funciona recursivamente também. (Consulte: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

Exemplo:

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

Vai resultar em:

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

)

Aqui está o 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

Percorra cada item da matriz e some os valores aos valores anteriores, se houver, se não apenas atribua o 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);

Resultado:

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

Ou simplesmente percorra cada submatriz e agrupe os valores de cada coluna. Eventualmente, somando-os:

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

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

0

Aqui você tem como geralmente faço esse tipo de operação.

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

Você poderia explicar esse código e por que ele responde à pergunta? Será mais útil do que despejar apenas um bloco de código sem qualquer explicação.
trincot de

claro!! Desculpe, sou espanhol e para mim explicar o código é a coisa mais difícil quando eu respondo uma pergunta! Obrigado pelo conselho @trincot
Luis González

0

Você pode tentar isto:

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

e finalmente:

print_r($c);

1
O que exatamente você está usando $ae $bquando liga array_map()? Por favor, melhore esta resposta apenas de código.
mickmackusa

0

isso funciona muito bem no meu projeto 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

Embora isso possa funcionar para o seu projeto Laravel, não é uma solução boa / viável para ESTA questão.
mickmackusa

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

Esta é uma duplicata de uma resposta de MUITOS anos antes. stackoverflow.com/a/1496697/2943403 Leia todas as respostas existentes antes de postar a sua, para que não haja redundâncias na mesma 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);

`

Reveja Como escrevo uma boa resposta . Respostas apenas em código são desencorajadas porque não explicam como resolvem o problema na pergunta. Você deve atualizar sua resposta para explicar o que isso faz e como melhora nas muitas respostas votadas a favor desta pergunta de 8 anos.
FluffyKitten

Basicamente, uma duplicata de uma resposta anterior: stackoverflow.com/a/20532196/2943403
mickmackusa

-2

Por exemplo, você pode retirar todos os campos de um resultado como este abaixo.

Estou escolhendo o 'equilíbrio' de uma matriz e salvando em uma variável

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

então, na próxima linha, você pode somar assim:

$sum =  $kii->sum(); 

Espero que ajude.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.