I have data as below :
Array
(
[1] => Array
(
[A] => Array
(
[AA] => 3
[AB] => 5
)
[B] => Array
(
[BA] => 2
)
[2] => Array
(
[C] => Array
(
[CA] => 4
)
[D] => Array
(
[DA] => 1
[DB] => 2
)
)
[3] => Array
(
[E] => Array
(
[EA] => 1
[EB] => 2
[EC] => 3
)
[F] => Array
(
[FA] => 0
[FB] => 7
[FC] => 7
)
)
I want to sum the value and this is my expectation :
Array(
[1] => 10
[2] => 7
[3] => 20
)
Here is my code that I used for summing the value :
$total[$country_id][$province_id][$city_id] = $amount;
$result = array();
foreach( $total as $key => $val ){
$total[$key] = array_sum ( $val );
}
can someone explain what is wrong with my code or explain how foreach work? because the result of my code is 0 and actually I just studied around 1 week about foreach. Thanks
As you want to know more about foreach
, here is a more verbose solution using it :
$total = 0;
$totalByCountry = [];
// iterate over each country
foreach ($arr as $countryId => $provinces) {
$totalByCountry[$countryId] = 0;
// iterate over each province
foreach ($provinces as $provinceId => $cities) {
// iterate over each city
foreach ($cities as $cityId => $value) {
$totalByCountry[$countryId] += $value;
$total += $value;
}
}
}
Result of var_dump(totalByCountry)
:
array (size=3)
1 => int 10
2 => int 7
3 => int 20
Result of var_dump($total)
:
int 37
-- edit --
In real world project, you better be less verbose and use php functions made for this kind of situation like array_walk_recursive(), as in Philipp Maurer and Firoz Ahmad answers.
print the $total,When coming to the foreach, $val is an array. so when calling array_sum function, it sums the first array and assign the total to a new array's first element. That is how this is working. The reason why you code is not working, there should be a foreach outside the foreach that you have been provided. Remove this foreach from above foreach's scope.
<?php
$x=[0=>[1,2,3],1=>[2,3,4]];
$result = array();
foreach( $x as $key => $val ){
$total[$key] = array_sum ( $val );
}
var_dump($total);
?>
If your array is 3 dimentional Code is like this,
$y=[0=>[0=>[1,2,3],1=>[3,4,5]],1=>[0=>[5,6,7],1=>[8,9,10]]];
$result = array();
foreach( $y as $vals ){
foreach( $vals as $key => $val ){
$total[$key] = array_sum ( $val );
}
}
var_dump($total);
The problem with your foreach
is, that your array is three layers deep, while your foreach
only traverses the first and array_sum()
only calculates the second layer.
An example of your foreach:
$total = [
0 => [
'A' => [
'AA' => 1,
'AB' => 2
],
'B' => [
'BA' => 3,
'BB' => 4
]
]
];
foreach( $total as $key => $val ){
$total[$key] = array_sum ( $val );
}
The foreach
will iterate over the $total
array. This is the iteraton for the example:
$key = 0
; $value = ['A'=>['AA'=>1,'AB'=>2], 'B'=>['BA'=>3,'BB'=>4]]
array_sum()
on $value
. array_sum()
adds the children of the provided array together, if they are numeric. Sadly $value
is a two dimensional array and its children are arrays, so they are not numeric. That is why 0
is returned for it.A solution to your problem would be to use the array_walk_recursive()
function, that traverses inner arrays and calls a function upon them, that you can specify:
$sum = 0;
array_walk_recursive($total, function($value) use (&$sum) {
$sum += $value;
});
The specified function adds the value of each leaf in your array to the specified variable $sum
, that is given by reference to the function.
To achieve your desired output, you at first should iterate over your array and check if there exists any sub array then, again traverse all array members by using array_walk_recursive()
function
<?php
$arr = [
[
'A' => [
'AA' => 3,
'BB' => 5,
'CC' => [
'DD' => 4,
'EE' => 5
]
],
'B' => [
'BA' => 2
]
],
[
'C' => [
'CC' => 3,
'CCC' => 2,
],
'D' => [
'DD' => 2
]
],
5,
[
2,
7
]
];
$arrSum = [];
$count = count($arr);
for ($i = 0; $i < $count; $i++) {
$sum = 0;
if(is_array($arr[$i])) {
array_walk_recursive($arr[$i], function ($item, $key) use (&$sum) {
$sum += $item;
});
}
else {
$sum += $arr[$i];
}
$arrSum [] = $sum;
$sum = 0;
}
var_dump($arrSum);