Come sommare tutti i valori delle colonne in un array multidimensionale?


116

Come posso aggiungere tutti i valori colonnari per chiave associativa? Notare che i set di chiavi sono dinamici.

Matrice di input:

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

Risultato desiderato:

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

Per una situazione comune, due array multidimensionali non hanno esattamente le stesse chiavi. unisci / somma array multi dimensionale php
Kris Roofe

Risposte:


92
$sumArray = array();

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

print_r($sumArray);

49
Ciò genererà avvisi per la prima iterazione poiché le chiavi non esistono ancora.
Gumbo

Se ci sono n array?
Muhammad Usman

2
@RanaMuhammadUsman: se ci sono narray, usa questa soluzione .
Amal Murali

2
array_reduce suoni la più bella per me stackoverflow.com/questions/14195916/...
Bill'o

13
Per evitare gli avvisi potresti sostituire la riga che assegna i valori a $ sumArray a: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ valore: $ sumArray [$ id] = $ valore;
Dave O'Brien

185

È possibile utilizzare array_walk_recursive()per ottenere una soluzione generale per il problema ( quella in cui ogni array interno può avere chiavi univoche ).

$final = array();

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

Esempio con array_walk_recursive()per il caso generale

Inoltre, dal momento che PHP 5.5 è possibile utilizzare la array_column()funzione per ottenere il risultato che si desidera per la chiave esatta , [gozhi]ad esempio:

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

Esempio con array_column()per la chiave specificata

Se vuoi ottenere la somma totale di tutti gli array interni con le stesse chiavi ( il risultato desiderato che hai pubblicato ), puoi fare qualcosa del genere ( tenendo presente che il primo array interno deve avere la stessa struttura degli altri ):

$final = array_shift($input);

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

unset($value);

Esempio con array_column()caso in cui tutti gli array interni abbiano le stesse chiavi

Se desideri una soluzione generale per il caso che utilizzi, array_column()in un primo momento potresti prendere in considerazione di ottenere tutte le chiavi univoche, quindi ottenere la somma per ciascuna chiave:

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

Esempio con array_column()per il caso generale


31

Usa questo snippet:

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

Ho modificato la domanda per chiarire che questa soluzione è in qualche modo poco cotta in termini di fornitura dell'output desiderato dall'OP. Detto questo, se espandessi la tua risposta, molto probabilmente diventerebbe un duplicato delle risposte pubblicate in precedenza.
mickmackusa

28

Ecco una soluzione simile alle altre due:

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

Ma questo non ha bisogno di controllare se le chiavi dell'array esistono già e non genera nemmeno avvisi.


+1 soluzione molto intelligente per questa specifica struttura di array. Peccato che non funzioni nel caso più generale di array tutti strutturati come il risultato finale.
Todd Chaffee

22

Può anche essere fatto 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
Perfetto per n numeri di array
Dushyant Joshi

1
Come cambieresti questo per N numeri di array?
Pathros

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

3
Nota che questo ti darà avvisi PHP (indice indefinito) ogni volta che accedi a $ newarr [$ key] sul lato destro dell'assegnazione, quando tali valori non esistono ancora.
Anti Veeranna

Penso di aggiungere un segno di spunta per inizializzare $ newarr [$ key]
Graviton

4
PER FAVORE, lasciate commenti se votate qualcuno per difetto ... Non c'è modo di migliorare la soluzione se non lasciate commenti.
Todd Chaffee

@Graviton Non ho downvote, ma affermerò che ogni risposta di StackOverflow dovrebbe includere alcune spiegazioni su come funziona la soluzione e / o perché è consigliabile. Ricorda che ogni pagina di questo sito / rete è una risorsa educativa per migliaia e migliaia di sviluppatori con una vasta gamma di abilità / conoscenze. (Se ho downvotato ogni volta che ho trovato una risposta solo codice, avrei esaurito i punti rep.)
mickmackusa

5

Un'altra versione, con alcuni vantaggi di seguito.

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

}

Volevo combinare il meglio delle risposte di Gumbo, Graviton e Chris J con i seguenti obiettivi in ​​modo da poterlo utilizzare nella mia app:

a) Inizializza le chiavi dell'array 'sum' al di fuori del ciclo (Gumbo). Dovrebbe aiutare con le prestazioni su array molto grandi (non ancora testato!). Elimina gli avvisi.

b) La logica principale è facile da capire senza toccare i manuali. (Graviton, Chris J).

c) Risolvi il problema più generale di aggiungere i valori di due array qualsiasi con le stesse chiavi e renderlo meno dipendente dalla struttura del sotto-array.

A differenza della soluzione di Gumbo, puoi riutilizzarla nei casi in cui i valori non sono in sotto-array. Immagina nell'esempio seguente che $arr1e $arr2non siano hardcoded, ma vengano restituiti come risultato della chiamata di una funzione all'interno di un ciclo.

$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

Può anche essere fatto 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'));

Non così leggibile come le soluzioni precedenti ma funziona :)


3

Ecco una versione in cui le chiavi dell'array potrebbero non essere le stesse per entrambi gli array, ma vuoi che siano tutte presenti nell'array finale.

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

Dobbiamo prima controllare se la chiave dell'array esiste.

CODICE:

$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 con convalida della chiave dell'array:

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

OUTPUT senza convalida della chiave dell'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
)

Questa è una cattiva pratica anche se stampa l'output. Controlla sempre prima se la chiave esiste.


1

Per coloro che sono arrivati ​​qui e sono alla ricerca di una soluzione che unisca N array E somma anche i valori di chiavi identiche trovate negli N array, ho scritto questa funzione che funziona anche in modo ricorsivo. (Vedi: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

Esempio:

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

Risulterà in:

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

)

Ecco il codice:

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

Passa attraverso ogni elemento della matrice e somma i valori ai valori precedenti se esistono, altrimenti assegna semplicemente il valore.

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

Produzione:

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

O semplicemente scorrere ogni sottoarray e raggruppare i valori per ogni colonna. Alla fine sommandoli:

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

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

0

Ecco come faccio di solito questo tipo di operazioni.

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

Per favore, potresti fornire una spiegazione di questo codice e perché risponde alla domanda? Sarà più utile che scaricare solo un blocco di codice senza alcuna spiegazione.
trincot

ovviamente!! Scusa, sono spagnolo e per me spiegare il codice è la cosa più difficile quando rispondo a una domanda! Grazie per il tuo consiglio @trincot
Luis González

0

Puoi provare questo:

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

e infine:

print_r($c);

1
Che cosa stai usando esattamente $ae $bquando chiami array_map()? Migliora questa risposta solo in codice.
mickmackusa

0

funziona alla grande sul mio progetto 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

Sebbene questo possa funzionare per il tuo progetto Laravel, questa non è una soluzione buona / praticabile per QUESTA domanda.
mickmackusa

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

Questo è un duplicato di una risposta di MOLTI anni prima. stackoverflow.com/a/1496697/2943403 Si prega di leggere tutte le risposte esistenti prima di pubblicarne una propria in modo che non ci siano ridondanze sulla stessa pagina.
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);

`

Si prega di rivedere Come scrivo una buona risposta . Le risposte di solo codice sono scoraggiate perché non spiegano come risolvono il problema nella domanda. Dovresti aggiornare la tua risposta per spiegare cosa fa e come migliora le molte risposte votate positivamente che questa domanda di 8 anni ha già.
FluffyKitten

Fondamentalmente un duplicato di una precedente risposta: stackoverflow.com/a/20532196/2943403
mickmackusa

-2

Ad esempio, puoi strappare tutti i campi da un risultato come questo di seguito.

Sto selezionando il "saldo" da un array e lo salvo in una variabile

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

quindi nella riga successiva puoi sommare in questo modo:

$sum =  $kii->sum(); 

Spero che sia d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.