Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum of multidimensional array in same format

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.

like image 567
Happy Coder Avatar asked Jan 01 '26 00:01

Happy Coder


2 Answers

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

like image 80
ABelikov Avatar answered Jan 03 '26 16:01

ABelikov


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.

like image 31
sevavietl Avatar answered Jan 03 '26 16:01

sevavietl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!