如何使用递归求和多维数组中的特定值?

时间:2018-11-10 07:08:13

标签: php arrays json recursion multidimensional-array

我有一个多级对象数据,其结构类似于下面的窗口。

我正在尝试

  • 汇总最高用户的所有直接打包值或仅说parents
  • 求和children树中所有嵌套的间接包值。

预计最终结果将类似于: [{"sum_direct": 600},{"sum_indirect": 3000}]

我需要帮助才能知道我做错了什么:

function sumDirect($c) {
    if(count($c) > 0){
        $sum = 0;
        foreach ($c as $package) {
            $sum += $package['package']['direct'];
        }
    } else {
        $sum = 0;
    }
    return $sum;
}

function sumIndirect($c) {
    if(count($c) > 0){
        $sum = 0;
        foreach ($c as $package) {
            if(count($package['children']) > 0) {
                foreach ($package['children'] as $children){
                    $sum += $children['indirect'];
                    $sum += sumIndirect($children);
                }
            }
        }
    } else {
        $sum = 0;
    }
    return $sum;
}

样本输入:

{
  "users": [{
      "user_id": 2,
      "ref_id": 1,
      "package": [{
          "name": "Basic"
        },
        {
          "direct": 200
        },
        {
          "indirect": 100
        }
      ],
      "children": [{
          "user_id": 58,
          "ref_id": 2,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 59,
          "ref_id": 2,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 111,
          "ref_id": 2,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 116,
          "ref_id": 2,
          "package": [{
              "name": "Diamond"
            },
            {
              "direct": 1000
            },
            {
              "indirect": 500
            }
          ],
          "children": 0
        },
        {
          "user_id": 119,
          "ref_id": 2,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        }
      ]
    },
    {
      "user_id": 100,
      "ref_id": 1,
      "package": [{
          "name": "Basic"
        },
        {
          "direct": 200
        },
        {
          "indirect": 100
        }
      ],
      "children": [{
          "user_id": 101,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 102,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 103,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 104,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 105,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 106,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 107,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 108,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 109,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 110,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        },
        {
          "user_id": 117,
          "ref_id": 100,
          "package": [{
              "name": "Diamond"
            },
            {
              "direct": 1000
            },
            {
              "indirect": 500
            }
          ],
          "children": 0
        },
        {
          "user_id": 129,
          "ref_id": 100,
          "package": [{
              "name": "Diamond"
            },
            {
              "direct": 1000
            },
            {
              "indirect": 500
            }
          ],
          "children": 0
        },
        {
          "user_id": 130,
          "ref_id": 100,
          "package": [{
              "name": "Basic"
            },
            {
              "direct": 200
            },
            {
              "indirect": 100
            }
          ],
          "children": 0
        }
      ]
    }
  ]
}

users.json处填写数据

2 个答案:

答案 0 :(得分:0)

一种简单的方法可以基于一对foreach,每个嵌套另一个

$result['sum_direct'] = 0;
$result['sum_indirect'] = 0;

$myArray = json_decode($myJsonString, TRUE)
  foreach($myArray['users'] as  $value){
  $result['sum_direct'] += $value['package']['direct'];
  foreach($value['children']['package'] as  $value2){
    $result['sum_indirect']  += $value2['indirect'];
  }
}

$jsonResult= json_encode($result);

答案 1 :(得分:0)

“父”直接值似乎不需要递归,因此可以通过直接foreach循环来完成。

“儿童”间接值需要递归。我选择使用(A2, A4) (A4, A3)访问数组中的每个“叶子节点”。这也将存储父母的间接值,因此我在(A1, A2)完成后减去了这些值。

代码:(Demo

array_walk_recursive()

使用查询中的数据输出:

array_walk_recursive()

使用来自github的完整json输出:

$result['sum_direct'] = 0;
$result['sum_indirect'] = 0;
$parents_indirect = 0;
echo "<pre>";
$array = json_decode($json, true)['users'];
foreach ($array as $users) {
    $result['sum_direct'] += $users['package'][1]['direct'];
    $parents_indirect += $users['package'][2]['indirect'];
}
array_walk_recursive($array, function ($v, $k) use (&$result) {
        if ($k === 'indirect') {
            $result['sum_indirect'] += $v;
        }
    });
$result['sum_indirect'] -= $parents_indirect;

echo json_encode($result);