Comment additionner toutes les valeurs de colonne dans un tableau multidimensionnel?

116

Comment puis-je ajouter toutes les valeurs en colonnes par clé associative? Notez que les jeux de clés sont dynamiques.

Tableau d'entrée:

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

Résultat désiré:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)
marknt15
la source
Pour une situation courante, deux tableaux multidimensionnels n'ont pas exactement les mêmes clés. merge / sum multi dimentional array php
Kris Roofe

Réponses:

92
$sumArray = array();

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

print_r($sumArray);
Chris J
la source
49
Cela lancera des notifications pour la première itération car les clés n'existent pas encore.
Gumbo
S'il y a n tableaux?
Muhammad Usman
2
@RanaMuhammadUsman: S'il y a des ntableaux, utilisez cette solution .
Amal Murali
2
array_reduce me semble le plus joli stackoverflow.com/questions/14195916/…
Bill'o
13
Pour éviter les avis, vous pouvez remplacer la ligne affectant les valeurs de $ sumArray à: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ valeur: $ sumArray [$ id] = $ valeur;
Dave O'Brien
185

Vous pouvez utiliser array_walk_recursive()pour obtenir une solution générale à votre problème ( celle où chaque tableau interne peut éventuellement avoir des clés uniques ).

$final = array();

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

Exemple avec array_walk_recursive()pour le cas général

En outre, depuis PHP 5.5 , vous pouvez utiliser la array_column()fonction pour obtenir le résultat souhaité pour la clé exacte , [gozhi]par exemple:

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

Exemple avec array_column()pour la clé spécifiée

Si vous voulez obtenir la somme totale de tous les tableaux internes avec les mêmes clés ( le résultat souhaité que vous avez publié ), vous pouvez faire quelque chose comme ceci (en gardant à l'esprit que le premier tableau interne doit avoir la même structure que les autres ):

$final = array_shift($input);

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

unset($value);

Exemple avec array_column()au cas où tous les tableaux internes ont les mêmes clés

Si vous voulez une solution de cas général en utilisant, array_column()vous pouvez d'abord envisager d'obtenir toutes les clés uniques, puis obtenir la somme pour chaque clé:

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

Exemple avec array_column()pour le cas général

potashine
la source
31

Utilisez cet extrait:

$key = 'gozhi';
$sum = array_sum(array_column($array,$key));
Tan Ory Jaka Perdana
la source
J'ai édité la question pour clarifier que cette solution est quelque peu insuffisamment cuite en termes de livraison du résultat souhaité par l'OP. Cela dit, si vous étendiez votre réponse, cela deviendrait très probablement un double des réponses publiées précédemment.
mickmackusa
28

Voici une solution similaire aux deux autres:

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

Mais cela n'a pas besoin de vérifier si les clés du tableau existent déjà et ne lance pas non plus d'avis.

Gombo
la source
+1 solution très intelligente pour cette structure de tableau spécifique. Dommage que cela ne fonctionne pas dans le cas plus général des tableaux tous structurés comme le résultat final.
Todd Chaffee
22

Cela peut également être fait en utilisant 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());
}
npcoda
la source
1
Parfait pour n nombres de tableaux
Dushyant Joshi
1
Comment changeriez-vous cela pour N nombres de tableaux?
Pathros
12
$newarr=array();
foreach($arrs as $value)
{
  foreach($value as $key=>$secondValue)
   {
       if(!isset($newarr[$key]))
        {
           $newarr[$key]=0;
        }
       $newarr[$key]+=$secondValue;
   }
}
Graviton
la source
3
Notez que cela vous donnera des avis PHP (index non défini) chaque fois que vous accéderez à $ newarr [$ key] sur le côté droit de votre affectation, lorsque de telles valeurs n'existent pas encore.
Anti Veeranna
Je pense ajouter un chèque pour initialiser le $ newarr [$ key]
Graviton
4
VEUILLEZ laisser des commentaires si vous votez contre quelqu'un ... Il n'y a aucun moyen d'améliorer la solution si vous ne laissez pas de commentaires.
Todd Chaffee
@Graviton Je n'ai pas voté contre, mais je dirai que chaque réponse de StackOverflow devrait inclure des explications sur le fonctionnement de la solution et / ou pourquoi elle est souhaitable. N'oubliez pas que chaque page de ce site / réseau est une ressource éducative pour des milliers et des milliers de développeurs possédant un large éventail de compétences / connaissances. (Si je refusais chaque fois que je trouvais une réponse de code uniquement, je
manquerais de
5

Une autre version, avec quelques avantages ci-dessous.

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

}

Je voulais combiner le meilleur des réponses de Gumbo, Graviton et Chris J avec les objectifs suivants afin de pouvoir l'utiliser dans mon application:

a) Initialisez les clés du tableau 'sum' en dehors de la boucle (Gumbo). Cela devrait améliorer les performances sur de très grands tableaux (pas encore testés!). Élimine les avis.

b) La logique principale est facile à comprendre sans toucher aux manuels. (Graviton, Chris J).

c) Résoudre le problème plus général de l'addition des valeurs de deux tableaux quelconques avec les mêmes clés et le rendre moins dépendant de la structure du sous-tableau.

Contrairement à la solution de Gumbo, vous pouvez la réutiliser dans les cas où les valeurs ne sont pas dans des sous-tableaux. Imaginez dans l'exemple ci - dessous que $arr1et $arr2ne sont pas codés en dur, mais sont retournés à la suite d'appeler une fonction dans une boucle.

$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);
Todd Chaffee
la source
4

Cela peut également être fait en utilisant 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'));

Pas si lisible que les solutions précédentes mais ça marche :)

Filip Górczyński
la source
3

Voici une version où les clés du tableau peuvent ne pas être les mêmes pour les deux tableaux, mais vous voulez qu'elles soient toutes là dans le tableau 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;
}
Bollis
la source
3

Nous devons d'abord vérifier si la clé de tableau existe.

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

SORTIE avec validation de clé de tableau:

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

SORTIE sans validation de clé de tableau:

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
)

C'est une mauvaise pratique bien qu'elle imprime la sortie. Vérifiez toujours d'abord si la clé existe.

Bluetree
la source
1

Pour ceux qui ont atterri ici et recherchent une solution qui fusionne N tableaux ET additionne également les valeurs de clés identiques trouvées dans les N tableaux, j'ai écrit cette fonction qui fonctionne également de manière récursive. (Voir: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

Exemple:

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

Aura pour résultat:

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

)

Voici le 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;

}

?>
pseudo
la source
1

Parcourez chaque élément du tableau et additionnez les valeurs aux valeurs précédentes si elles existent, sinon affectez simplement la valeur.

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

Production:

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

Ou parcourez simplement chaque sous-tableau et regroupez les valeurs de chaque colonne. En les résumant finalement:

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

$sums = array_map('array_sum', $grouped);
Progrock
la source
0

Voici comment je fais habituellement ce genre d'opérations.

// 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);
Luis González
la source
Pouvez-vous expliquer ce code et pourquoi il répond à la question? Ce sera plus utile que de vider juste un bloc de code sans aucune explication.
trincot
bien sûr!! Désolé, je suis espagnol et pour moi, expliquer le code est la chose la plus difficile quand je réponds à une question! Merci pour vos conseils @trincot
Luis González
0

Vous pouvez essayer ceci:

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

et enfin:

print_r($c);
1990rk4
la source
1
Pourquoi utilisez-vous exactement $aet $bquand vous appelez array_map()? Veuillez améliorer cette réponse en code uniquement.
mickmackusa
0

cela fonctionne très bien sur mon projet 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
Maurice Wagura
la source
Bien que cela puisse fonctionner pour votre projet Laravel, ce n'est pas une bonne solution / réalisable pour CETTE question.
mickmackusa
-1
$sumArray = array();
foreach ($myArray as $k => $subArray) {
    foreach ($subArray as $id => $value) {
        if (!isset($sumArray[$id])) {
            $sumArray[$id] = 0;
        }
        $sumArray[$id]+=$value;
    }
}
Channeth Khon
la source
Ceci est le double d'une réponse de BEAUCOUP d'années plus tôt. stackoverflow.com/a/1496697/2943403 Veuillez lire toutes les réponses existantes avant de publier les vôtres afin qu'il n'y ait pas de redondance sur la même page.
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);

`
Soliman Mahmoud Soliman
la source
Veuillez consulter Comment écrire une bonne réponse . Les réponses basées uniquement sur le code sont déconseillées car elles n'expliquent pas comment elles résolvent le problème dans la question. Vous devriez mettre à jour votre réponse pour expliquer ce que cela fait et comment cela améliore les nombreuses réponses votées pour cette question de 8 ans déjà.
FluffyKitten
Fondamentalement, un double d'une réponse précédente: stackoverflow.com/a/20532196/2943403
mickmackusa
-2

Par exemple, vous pouvez extraire tous les champs d'un résultat comme celui-ci ci-dessous.

Je choisis le `` solde '' d'un tableau et je l'enregistre dans une variable

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

puis sur la ligne suivante, vous pouvez résumer comme ceci:

$sum =  $kii->sum(); 

J'espère que ça aide.

Emmanuel Iyen-Mediatrees
la source