3

I have a multidimensional array in the following format :

array (
  0 => 
  array (
    'manual' => 1,
    'cancelled' => 1,
    'expired' => 1,
    'earned' => 1,
    'user' => 
    array (
      'user1' => 1,
      'user2' => 1,
      'user3' => 1,
      'user4' => 1,
    ),
    'transfer' => 
    array (
      'transfer1' => 
      array (
        'key1' => 1,
        'key2' => 1,
        'key3' => 1,
      ),
      'transfer2' => 
      array (
        'key5' => 1,
        'key6' => 1,
        'key7' => 1,
      ),
    ),
    'date' => '2018-03-07',
  ),
  1 => 
  array (
    'manual' => 1,
    'cancelled' => 1,
    'expired' => 1,
    'earned' => 1,
    'user' => 
    array (
      'user1' => 1,
      'user2' => 1,
      'user3' => 1,
      'user4' => 1,
    ),
    'transfer' => 
    array (
      'transfer1' => 
      array (
        'key1' => 1,
        'key2' => 1,
        'key3' => 1,
      ),
      'transfer2' => 
      array (
        'key5' => 1,
        'key6' => 1,
        'key7' => 1,
      ),
    ),
    'date' => '2018-03-08',
  ),

)I need to calculate the sum of the array values with same index. So the total array should be as the following

Array
(
    [total] => Array
        (
            [manual] => 2
            [cancelled] => 2
            [expired] => 2
            [earned] => 2
            [user] => Array
                (
                    [user1] => 2
                    [user2] => 2
                    [user3] => 2
                    [user4] => 2
                )

            [transfer] => Array
                (
                    [transfer1] => Array
                        (
                            [key1] => 2
                            [key2] => 2
                            [key3] => 2
                        )

                    [transfer2] => Array
                        (
                            [key5] => 2
                            [key6] => 2
                            [key7] => 2
                        )
        )

That is the total should have the same format except date, but it needs to show the total sum of the value. How can this be done in PHP ? I have used the following code

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

unset($value);

var_dump($final);

where $input is considered as the first array and $final is total. I think this only work with single indexes.

Happy Coder
  • 4,255
  • 13
  • 75
  • 152
  • `same index.`-> whcih same index you used to compare ? – Alive to die - Anant Mar 19 '18 at 11:36
  • @AlivetoDie the index `manual` in the 0th element needs to be added to `manual` in the first element. So in total the value for `manual` index is 2. This is same for all other indexes. – Happy Coder Mar 19 '18 at 11:38
  • so based on manual you are going to check sub-arrays need to be added or not? Am i right? – Alive to die - Anant Mar 19 '18 at 11:39
  • you can find the solution here https://stackoverflow.com/questions/1496682/sum-array-values-of-the-same-key – kashalo Mar 19 '18 at 11:42
  • nope. It is like `$total['total']['manual'] = $array[0]['manual']+ $array[1]['manual']` and `$total['total']['cancelled'] = $array[0]['cancelled']+ $array[1]['cancelled']` and `$total['total']['user']['user1'] = $array[0]['user']['user1']+ $array[1]['user']['user1']` – Happy Coder Mar 19 '18 at 11:44
  • @kashalo I have used the top voted answer given there. But it is throwing error. I think it will only work arrays without nested groups. – Happy Coder Mar 19 '18 at 11:45
  • use the code of the link:- https://eval.in/974483 and try and let me know worked or not? – Alive to die - Anant Mar 19 '18 at 11:50
  • @AlivetoDie actually it needs to add the values in these indexes. Not simply one and also I have a number of items in the main array. not 2 – Happy Coder Mar 19 '18 at 11:54
  • `it needs to add the values in these indexes. `-> i am unable to understand this. Please explain – Alive to die - Anant Mar 19 '18 at 11:55
  • @HappyCoder, can you, please, provide input in the form of `var_export`, instead of `print_r`. As this is not really a trivial question, so the people, trying to answer your question, might want to play with some code. And it is really hard to do when you cannot copy/paste the input. – sevavietl Mar 19 '18 at 12:41
  • @sevavietl edited the question and added var_export result – Happy Coder Mar 19 '18 at 13:08
  • @HappyCoder, thank you – sevavietl Mar 19 '18 at 13:23

2 Answers2

3

You can use recursive function which walk through all you "tree".

There

If element is array create same in result array and run function for each key. If it has a number, just add value to result.

Here is a SAMPLE

<?php
// Array with data
$arr=array(array('manual'=>1,'cancelled'=>1,'expired'=>1,'earned'=>1,'user'=>array('user1'=>1,'user2'=>1,'user3'=>1,'user4'=>1,),'transfer'=>array('transfer1'=>array('key1'=>1,'key2'=>1,'key3'=>1,),'transfer2'=>array('key5'=>1,'key6'=>1,'key7'=>1,)),'date'=>'2018-03-07',),array('manual'=>1,'cancelled'=>1,'expired'=>1,'earned'=>1,'user'=>array('user1'=>1,'user2'=>1,'user3'=>1,'user4'=>1,),'transfer'=>array('transfer1'=>array('key1'=>2,'key2'=>2,'key3'=>2,),'transfer2'=>array('key5'=>2,'key6'=>2,'key7'=>2,)),'date'=>'2018-03-08',)); 

//Init result array
$res=array('total'=>array());

foreach ($arr as $key=>$val) {
    //Run it for each element and store result to $res['total']
   countTotal($res['total'],$val);
}

//Show result
print_r($res);


/*
* Count totals for branch of array
* @param $res - reference to branch of result array
* @param $arr - branch of data array
*/
function countTotal(&$res,$arr) {
        foreach ($arr as $key=>$val) {
            if (is_array($val)) {
                //it's array. Create "branch" in $res and run countTotal() to calc total for it
                if (!isset($res[$key])) $res[$key]=array();
                countTotal($res[$key],$val);
            } else if (is_numeric($val)) {
                // it's number. Create "leaf" if need and add value.
                if (!isset($res[$key])) $res[$key]=0;
                $res[$key]+=$val;
            }
        }
}

As you see it use reference to branch of result array for accumulating totals

Results

    Array
    (
        [total] => Array
            (
                [manual] => 2
                [cancelled] => 2
                [expired] => 2
                [earned] => 2
                [user] => Array
                    (
                        [user1] => 2
                        [user2] => 2
                        [user3] => 2
                        [user4] => 2
                    )

                [transfer] => Array
                    (
                        [transfer1] => Array
                            (
                                [key1] => 3
                                [key2] => 3
                                [key3] => 3
                            )

                        [transfer2] => Array
                            (
                                [key5] => 3
                                [key6] => 3
                                [key7] => 3
                            )

                    )

            )

    )

In second "transfer" I have used "2" so it's "3" in sum

ABelikov
  • 613
  • 5
  • 10
1

You can write the recursive function like the following:

function array_sum_recursive_assoc($array, &$result = [])
{
    $keys = array_keys($array[0] ?? []);

    foreach ($keys as $key) {
        foreach (($column = array_column($array, $key)) as $value) {
            if (is_array($value)) {
                $result[$key] = [];
                array_sum_recursive_assoc($column, $result[$key]);
                continue 2;
            }

            // In this case date safe guard.
            if (!is_numeric($value)) {
                continue;
            }

            $result[$key] = ($result[$key] ?? 0) + $value;
        }
    }

    return $result;
}

var_dump(array_sum_recursive_assoc($array));

Here is the demo.

sevavietl
  • 3,762
  • 1
  • 14
  • 21