У меня есть массив со структурой, аналогичной приведенной ниже. Где есть иерархия
[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);
Я нашел решение, которое, кажется, работает для меня. Не проверял это тщательно но, похоже, работает до сих пор.
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
Я думаю о такой рекурсивной функции:
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
]