0

I have an array, with a structure similar to that below. Where there is a heirarchy

[2] => Array
        (
            [sumW] => 200.39
            [child] => Array
                (
                    [3] => Array
                        (
                            [sumW] => 300.00
                        )
                    [4] => Array
                        (
                            [sumW] => 100.28
                            [child] => Array
                                (
                                    [5] => Array
                                        (
                                            [sumW] => 600
                                        )

                                    [6] => Array
                                        (
                                            [sumW] => 150
                                        )

                                 )
                         )

                    [7] => Array
                        (
                            [sumW] => 30.00
                            [child] => Array
                                (
                                    [8] => Array
                                        (
                                            [sumW] => 100.00
                                        )

                                 )
                         )

                 )
        )

```

I can't figure out how to sum each array at EACH level of the array. So that each level has the sum of ITSELF AND the levels BELOW it.

So, for example, something like

[2]   = [tot] => 1480.67
 [3]  = [tot] => 300.00
 [4]  = [tot] => 850.28
  [5] = [tot] => 600.00
  [6] = [tot] => 150.00
 [7]  = [tot] => 130.00
  [8] = [tot] => 100.00

And so forth.

The array can be infinite levels deep, this only show 3 levels, but my hierarchy could extend deeper than 3 levels.

I've tried messing with array sum and with setting parent/child IDs in an array. The best I can do is get the values for 2->3,4,7. But I can't get [2] to include values form [5] and [6] and beyond.

EDIT:

Here is one approach I tried. I have parent_ids and category_ids from my raw data. And this got my sums 1 level deep at each level. But doesn't sum everything down the hierarchy.

$tot=[];
$getSum = function ($array, $pid = null) use (&$getSum, &$tot) {
             $rpt = new Report;
             foreach ($array as $item) {
         // This returns my database value for this category.
                 $sum = $rpt->getCategoryTotal($item->category_id);

                 if($item->parent_id == $pid) {

                     if(!isset($tot[$item->category_id])){
                         $tot[$item->category_id] = $sum;
                     }   

                     if(isset($tot[$item->parent_id])){
                         $tot[$item->parent_id] += $sum;
                     }   

                     $child = $getSum($item->children, $item->category_id);
                 }
             }           
             return $sum;
         };

$result = $getSum($myDbData);
return dd($tot);
Nertskull
  • 491
  • 6
  • 20

2 Answers2

0

I found a solution that seems to work for me. Haven't tested it thoroughly but it seems to be working thus far.

     function setTotals($category) {
         $category['totalW'] = $category['sumW'];
         if (isset($category['child']) && is_array($category['child'])) {
             $sub = [];
             $i = 0;
             foreach ($category['child'] as $cat) {
                 $sub[] = setTotals($cat);
                 $category['totalW'] += $sub[$i]['totalW'];
                 $i++;
             }
             $category['child'] = $sub;
         }
         return $category;
     }   
     setTotals($myArray);

That works on the array structure posted in the question, and adds a 'total' line to each level, along with the sum for that level, including the level.

Hopefully this helps someone else.

Credit: I found this here that helped me make this work. codepad

Nertskull
  • 491
  • 6
  • 20
0

I think about a recursive function like that:

public function recursiveSum(array $source)
{
    $children = $source['child'] ?? [];

    $sum = $source['sumW'] ?? 0;

    foreach($children as $index => $child)
    {
        $source['child'][$index] = $this->recursiveSum($child);
        $sum += $source['child'][$index]['total'];
    }

    $source['total'] = $sum;
    return $source;
}

If you need a result for the upper level, this one will need the "child" key.

Here is an implementation of your datas I made for testing:

$datas = [
    'child' => [
        2 => [
            'sumW' => 200.39,
            'child' => [
                3 => [
                    'sumW' => 300,
                ],
                4 => [
                    'sumW' => 100.28,
                    'child' => [
                        5 => [
                            'sumW' => 600,
                        ],
                        6 => [
                            'sumW' => 150,
                        ],
                    ]
                ],
                7 => [
                    'sumW' => 30,
                    'child' => [
                        5 => [
                            'sumW' => 100,
                        ],
                    ],
                ],
            ],
        ],
    ]
];

And the output:

array:2 [▼
    "child" => array:1 [▼
        2 => array:3 [▼
            "sumW" => 200.39
            "child" => array:3 [▼
                3 => array:2 [▼
                    "sumW" => 300
                    "total" => 300
                ]
                4 => array:3 [▼
                    "sumW" => 100.28
                    "child" => array:2 [▼
                        5 => array:2 [▼
                            "sumW" => 600
                            "total" => 600
                        ]
                        6 => array:2 [▼
                            "sumW" => 150
                            "total" => 150
                        ]
                    ]
                    "total" => 850.28
                ]
                7 => array:3 [▼
                    "sumW" => 30
                    "child" => array:1 [▼
                        5 => array:2 [▼
                            "sumW" => 100
                            "total" => 100
                        ]
                    ]
                    "total" => 130
                ]
            ]
            "total" => 1480.67
        ]
    ]
    "total" => 1480.67
]
Elie D.
  • 1
  • 2