Jak zsumować wszystkie wartości kolumn w tablicy wielowymiarowej?

116

Jak mogę dodać wszystkie wartości kolumnowe według klucza asocjacyjnego? Zwróć uwagę, że zestawy kluczy są dynamiczne.

Tablica wejściowa:

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

Pożądany rezultat:

Array
(
    [gozhi] => 10
    [uzorong] => 1
    [ngangla] => 8
    [langthel] => 10
)
marknt15
źródło
W typowej sytuacji dwie tablice wielowymiarowe nie mają dokładnie takich samych kluczy. merge / sum multi
dimentional

Odpowiedzi:

92
$sumArray = array();

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

print_r($sumArray);
Chris J
źródło
49
Spowoduje to wyświetlenie powiadomień przy pierwszej iteracji, ponieważ klucze jeszcze nie istnieją.
Gumbo
Jeśli istnieje n tablic?
Muhammad Usman
2
@RanaMuhammadUsman: Jeśli istnieją ntablice, użyj tego rozwiązania .
Amal Murali
2
array_reduce brzmi dla mnie najpiękniej stackoverflow.com/questions/14195916/…
Bill'o
13
Aby uniknąć powiadomień, możesz zamienić wiersz przypisujący wartości do $ sumArray na: array_key_exists ($ id, $ sumArray)? $ sumArray [$ id] + = $ wartość: $ sumArray [$ id] = $ wartość;
Dave O'Brien
185

Możesz użyć, array_walk_recursive()aby uzyskać ogólne rozwiązanie problemu ( takie, w którym każda wewnętrzna tablica może mieć unikalne klucze ).

$final = array();

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

Przykład z array_walk_recursive()dla przypadku ogólnego

Ponadto, ponieważ PHP 5.5 można użyć array_column()funkcji do osiągnięcia rezultatu, który ma na dokładnym klucza , [gozhi]na przykład:

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

Przykład z array_column()dla określonego klucza

Jeśli chcesz uzyskać całkowitą sumę wszystkich wewnętrznych tablic z tymi samymi kluczami ( pożądany wynik, który opublikowałeś ), możesz zrobić coś takiego ( pamiętając, że pierwsza wewnętrzna tablica musi mieć taką samą strukturę jak pozostałe ):

$final = array_shift($input);

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

unset($value);

Przykład z array_column()case wszystkie tablice wewnętrzne mają te same klucze

Jeśli chcesz zastosować rozwiązanie dla przypadków ogólnych, array_column()na początku możesz rozważyć uzyskanie wszystkich unikalnych kluczy, a następnie uzyskać sumę za każdy klucz:

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

Przykład z array_column()dla przypadku ogólnego

potaszyn
źródło
31

Użyj tego fragmentu:

$key = 'gozhi';
$sum = array_sum(array_column($array,$key));
Tan Ory Jaka Perdana
źródło
Zredagowałem pytanie, aby wyjaśnić, że to rozwiązanie jest nieco niedopracowane pod względem dostarczania pożądanych wyników PO. To powiedziawszy, gdybyś rozszerzył swoją odpowiedź, najprawdopodobniej stałby się duplikatem wcześniej opublikowanych odpowiedzi.
mickmackusa
28

Oto rozwiązanie podobne do dwóch pozostałych:

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

Ale to nie musi sprawdzać, czy klucze tablic już istnieją i nie generują powiadomień.

Gumbo
źródło
+1 bardzo sprytne rozwiązanie dla tej specyficznej struktury tablicy. Szkoda, że ​​nie działa w bardziej ogólnym przypadku tablic, które mają strukturę podobną do wyniku końcowego.
Todd Chaffee,
22

Można to również zrobić za pomocą 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
źródło
1
Idealny dla n liczb tablicy
Dushyant Joshi
1
Jak zmieniłbyś to dla N liczb tablicy?
Pathros
12
$newarr=array();
foreach($arrs as $value)
{
  foreach($value as $key=>$secondValue)
   {
       if(!isset($newarr[$key]))
        {
           $newarr[$key]=0;
        }
       $newarr[$key]+=$secondValue;
   }
}
Graviton
źródło
3
Zauważ, że to da ci powiadomienia PHP (niezdefiniowany indeks) za każdym razem, gdy uzyskasz dostęp do $ newarr [$ klucz] po prawej stronie twojego przypisania, gdy takie wartości jeszcze nie istnieją.
Anti Veeranna,
Myślę, że dodam czek, aby zainicjować $ newarr [$ key]
Graviton
4
PROSZĘ zostawiaj komentarze, jeśli głosujesz na nie ... Nie ma możliwości ulepszenia rozwiązania, jeśli nie zostawisz komentarzy.
Todd Chaffee,
@Graviton Nie głosowałem przeciw, ale powiem, że każda odpowiedź StackOverflow powinna zawierać wyjaśnienie, jak działa to rozwiązanie i / lub dlaczego jest zalecane. Pamiętaj, że każda strona w tej witrynie / sieci jest zasobem edukacyjnym dla tysięcy programistów o szerokim zakresie umiejętności / wiedzy. (Gdybym przegłosował za każdym razem, gdy znajdowałem odpowiedź zawierającą tylko kod, zabrakło mi punktów rep.)
mickmackusa
5

Inna wersja, z kilkoma zaletami poniżej.

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

}

Chciałem połączyć najlepsze odpowiedzi Gumbo, Graviton i Chrisa J z następującymi celami, aby móc użyć tego w mojej aplikacji:

a) Zainicjuj klucze tablicy „sum” poza pętlą (Gumbo). Powinno pomóc w wydajności na bardzo dużych tablicach (jeszcze nie testowane!). Eliminuje powiadomienia.

b) Główna logika jest łatwa do zrozumienia bez sięgania po instrukcje. (Graviton, Chris J).

c) Rozwiąż bardziej ogólny problem polegający na dodaniu wartości dowolnych dwóch tablic z tymi samymi kluczami i uczynienie go mniej zależnym od struktury podtablicy.

W przeciwieństwie do rozwiązania Gumbo, możesz użyć tego ponownie w przypadkach, gdy wartości nie znajdują się w tablicach podrzędnych. Wyobraź sobie na przykład, że poniżej $arr1i $arr2nie są zakodowane, ale są zwracane w wyniku wywołania funkcji wewnątrz pętli.

$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
źródło
4

Można to również zrobić za pomocą 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'));

Nie tak czytelne jak poprzednie rozwiązania, ale działa :)

Filip Górczyński
źródło
3

Oto wersja, w której klucze tablic mogą nie być takie same dla obu tablic, ale chcesz, aby wszystkie znajdowały się w ostatecznej tablicy.

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
źródło
3

Musimy najpierw sprawdzić, czy klucz tablicy istnieje.

KOD:

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

WYJŚCIE z walidacją klucza tablicy:

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

WYJŚCIE bez weryfikacji klucza tablicy:

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
)

Jest to zła praktyka, chociaż drukuje dane wyjściowe. Zawsze najpierw sprawdź, czy klucz istnieje.

Bluetree
źródło
1

Dla tych, którzy wylądowali tutaj i szukają rozwiązania, które łączy N tablic ORAZ również sumuje wartości identycznych kluczy znalezionych w N tablicach, napisałem tę funkcję, która działa również rekurencyjnie. (Zobacz: https://gist.github.com/Nickology/f700e319cbafab5eaedc )

Przykład:

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

Spowoduje:

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

)

Oto kod:

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

}

?>
Nacięcie
źródło
1

Przejrzyj każdy element tablicy i zsumuj wartości z poprzednimi wartościami, jeśli istnieją, jeśli nie tylko przypisz wartość.

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

Wynik:

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

Lub po prostu przejrzyj każdą pod tablicę i pogrupuj wartości dla każdej kolumny. Ostatecznie je podsumowując:

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

$sums = array_map('array_sum', $grouped);
Progrock
źródło
0

Oto, jak zwykle wykonuję tego rodzaju operacje.

// 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
źródło
Czy mógłbyś wyjaśnić ten kod i dlaczego odpowiada na pytanie? Będzie to bardziej pomocne niż zrzucanie samego bloku kodu bez żadnego wyjaśnienia.
trincot
oczywiście!! Przepraszam, jestem Hiszpanem i dla mnie wyjaśnienie kodu jest najtrudniejszą rzeczą, kiedy odpowiadam na pytanie! Dzięki za radę @trincot
Luis González
0

Możesz spróbować tego:

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

i w końcu:

print_r($c);
1990rk4
źródło
1
Do czego dokładnie używasz $ai $bkiedy dzwonisz array_map()? Popraw tę odpowiedź zawierającą tylko kod.
mickmackusa
0

działa to świetnie w moim projekcie 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
źródło
Chociaż może to działać w przypadku twojego projektu Laravel, nie jest to dobre / wykonalne rozwiązanie dla TEGO pytania.
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
źródło
To jest kopia odpowiedzi sprzed WIELU lat. stackoverflow.com/a/1496697/2943403 Przeczytaj wszystkie istniejące odpowiedzi, zanim prześlesz własne, aby nie było nadmiarowości na tej samej stronie.
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
źródło
Proszę przejrzeć Jak napisać dobrą odpowiedź . Odpowiedzi zawierające tylko kod są odradzane, ponieważ nie wyjaśniają, w jaki sposób rozwiązują problem w pytaniu. Powinieneś zaktualizować swoją odpowiedź, aby wyjaśnić, co to robi i jak poprawia się w porównaniu z wieloma pozytywnymi odpowiedziami, które już ma to 8-letnie pytanie.
FluffyKitten,
Zasadniczo duplikat wcześniejszej odpowiedzi: stackoverflow.com/a/20532196/2943403
mickmackusa
-2

Na przykład możesz usunąć wszystkie pola z wyniku takiego jak ten poniżej.

Wybieram „saldo” z tablicy i zapisuję do zmiennej

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

następnie w następnym wierszu możesz podsumować w ten sposób:

$sum =  $kii->sum(); 

Mam nadzieję, że to pomoże.

Emmanuel Iyen-Mediatrees
źródło