Суммарный иерархический массив для каждого уровня массива / иерархии

У меня есть массив со структурой, аналогичной приведенной ниже. Где есть иерархия

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

)
)

)
)

```

Я не могу понять, как суммировать каждый массив на каждом уровне массива. Так что каждый уровень имеет сумму СЕБЯ И уровней НИЖЕ.

Так, например, что-то вроде

[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

И так далее.

Массив может иметь бесконечную глубину, это показывает только 3 уровня, но моя иерархия может расширяться глубже, чем на 3 уровня.

Я попытался возиться с суммой массива и с установкой родительских / дочерних идентификаторов в массиве. Лучшее, что я могу сделать, это получить значения для 2-> 3,4,7. Но я не могу заставить [2] включать значения из [5] и [6] и далее.

РЕДАКТИРОВАТЬ:

Вот один подход, который я попробовал. У меня есть parent_ids и category_ids из моих необработанных данных. И это получило мои суммы по 1 уровню на каждом уровне. Но не суммирует все по иерархии.

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

0

Решение

Я нашел решение, которое, кажется, работает для меня. Не проверял это тщательно но, похоже, работает до сих пор.

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

Это работает со структурой массива, размещенной в вопросе, и добавляет строку «итого» для каждого уровня вместе с суммой для этого уровня, включая уровень.

Надеюсь, это поможет кому-то еще.

Кредит: я нашел это здесь, которое помогло мне сделать эту работу.
codepad

0

Другие решения

Я думаю о такой рекурсивной функции:

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

Если вам нужен результат для верхнего уровня, для этого понадобится ключ «child».

Вот реализация ваших данных, которые я сделал для тестирования:

$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,
],
],
],
],
],
]
];

И вывод:

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
]
0

По вопросам рекламы [email protected]