Php 如何从递归树中列出所有可能性?
我得到了这些初始数据:Php 如何从递归树中列出所有可能性?,php,algorithm,tree,Php,Algorithm,Tree,我得到了这些初始数据: $h = [ 'id' => 'h', 'name' => 'H', 'config' => [], ]; $g = [ 'id' => 'g', 'name' => 'G', 'config' => [], ]; $f = [ 'id' => 'f', 'name' => 'F', 'config' => [ [
$h = [
'id' => 'h',
'name' => 'H',
'config' => [],
];
$g = [
'id' => 'g',
'name' => 'G',
'config' => [],
];
$f = [
'id' => 'f',
'name' => 'F',
'config' => [
[
['id' => $g['id'], 'quantity' => 1],
],
[
['id' => $h['id'], 'quantity' => 2],
],
],
];
$e = [
'id' => 'e',
'name' => 'E',
'config' => [],
];
$d = [
'id' => 'd',
'name' => 'D',
'config' => [
[
['id' => $e['id'], 'quantity' => 1],
['id' => $f['id'], 'quantity' => 3],
],
],
];
$c = [
'id' => 'c',
'name' => 'C',
'config' => [
[
['id' => $f['id'], 'quantity' => 1],
],
[
['id' => $e['id'], 'quantity' => 1],
],
],
];
$b = [
'id' => 'b',
'name' => 'B',
'config' => [
[
['id' => $c['id'], 'quantity' => 1],
],
],
];
$a = [
'id' => 'a',
'name' => 'A',
'config' => [
[
['id' => $d['id'], 'quantity' => 1],
],
[
['id' => $b['id'], 'quantity' => 1],
],
],
];
我将解释“配置”是如何工作的:
- 这是一系列的可能性(或)=>例如,从$c我们可以得到$f或$e
- 在这些可能性中有一个AND=>数组,例如,从$d开始,我们只有一个可能性是$e和$f
- 当配置为空时,它是一个叶子,因此我们可以停止
- 而棘手的部分(我认为)是,我们可以在每个配置中有数量,这意味着从$f开始,我们可以有$g一次或$h两次和从$d开始,我们有$e一次和$f三次
$possibilities = [
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'f',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'e',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'd',
'parent' => 'a',
...
],
[
'id' => 'e',
'parent' => 'd',
...
],
[
'id' => 'f-1',
'parent' => 'd',
...
],
[
'id' => 'f-2',
'parent' => 'd',
...
],
[
'id' => 'f-3',
'parent' => 'd',
...
],
[
'id' => 'g',
'parent' => 'f-1',
...
],
[
'id' => 'g',
'parent' => 'f-2',
...
],
[
'id' => 'g',
'parent' => 'f-3',
...
]
],
...
];
global $datas;
$datas = compact($a, $b, $c, $d, $e, $f, $g, $h);
function formatTree($tree)
{
if (empty($tree['config'])) {
return [$tree];
}
$config = $tree['config'];
unset($tree['config']);
$tree2 = [$tree];
foreach ($config as $item) {
$sub = formatTree($item);
$tree2 = array_merge($tree2, $sub);
}
return $tree2;
}
function preparePossibilities($item)
{
$possibilities = [];
if (empty($item['config'])) {
return [$item];
}
$config = $item['config'];
unset($item['config']);
foreach ($config as $or) {
$finalOr = [];
foreach ($or as $and) {
for ($i = 0; $i < ($and['quantity'] ?? 1); $i++) {
$finalOr[] = $and;
}
}
$item['config'] = $finalOr;
$possibilities[] = $item;
}
return $possibilities;
}
function are_same($trees)
{
$id = null;
foreach ($trees as $tree) {
$oldId = $id;
$id = $tree[0]['id'];
if (isset($oldId) && $oldId !== $id) {
return false;
}
}
return true;
}
function getAllTrees($id)
{
global $datas;
$data = current(array_filter($datas, static function ($d) use ($id) {
return $d['id'] === $id;
}));
$multiplePossibilities = preparePossibilities($data);
$allTrees = [];
foreach ($multiplePossibilities as $possibility) {
if (empty($possibility['config'])) {
return [$possibility];
}
$config = $possibility['config'];
unset($possibility['config']);
$trees = [];
foreach ($config as $i => $and) {
$subTrees = getAllTrees($and['id']);
foreach ($subTrees as $subTree) {
$trees[$i][] = $subTree;
}
}
$trees = array_values($trees);
if (count($trees) === 1) {
foreach ($trees as $tree) {
foreach ($tree as $t) {
$newP = $possibility;
$newP['config'] = [];
$newP['config'][] = $t;
$allTrees[] = $newP;
}
}
} elseif (are_same($trees)) {
$newP = $possibility;
$newP['config'] = $trees;
$allTrees[] = $newP;
} else {
$newP = $possibility;
$newP['config'] = [];
foreach ($trees as $tree) {
if (count($tree) === 1) {
$newP['config'][] = $tree[0];
} else {
foreach ($tree as $t) {
$p3 = $newP;
$p3['config'][] = $t;
$allTrees[] = $p3;
}
}
}
}
}
return $allTrees;
}
foreach (getAllTrees('a') as $tree) {
var_dump(formatTree($tree));
}
因此,我想提取并列出任何可能性,以及父节点(如果数量>1,则包括其编号)
到目前为止,我已经尝试过这样的方法:
$possibilities = [
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'f',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'e',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'd',
'parent' => 'a',
...
],
[
'id' => 'e',
'parent' => 'd',
...
],
[
'id' => 'f-1',
'parent' => 'd',
...
],
[
'id' => 'f-2',
'parent' => 'd',
...
],
[
'id' => 'f-3',
'parent' => 'd',
...
],
[
'id' => 'g',
'parent' => 'f-1',
...
],
[
'id' => 'g',
'parent' => 'f-2',
...
],
[
'id' => 'g',
'parent' => 'f-3',
...
]
],
...
];
global $datas;
$datas = compact($a, $b, $c, $d, $e, $f, $g, $h);
function formatTree($tree)
{
if (empty($tree['config'])) {
return [$tree];
}
$config = $tree['config'];
unset($tree['config']);
$tree2 = [$tree];
foreach ($config as $item) {
$sub = formatTree($item);
$tree2 = array_merge($tree2, $sub);
}
return $tree2;
}
function preparePossibilities($item)
{
$possibilities = [];
if (empty($item['config'])) {
return [$item];
}
$config = $item['config'];
unset($item['config']);
foreach ($config as $or) {
$finalOr = [];
foreach ($or as $and) {
for ($i = 0; $i < ($and['quantity'] ?? 1); $i++) {
$finalOr[] = $and;
}
}
$item['config'] = $finalOr;
$possibilities[] = $item;
}
return $possibilities;
}
function are_same($trees)
{
$id = null;
foreach ($trees as $tree) {
$oldId = $id;
$id = $tree[0]['id'];
if (isset($oldId) && $oldId !== $id) {
return false;
}
}
return true;
}
function getAllTrees($id)
{
global $datas;
$data = current(array_filter($datas, static function ($d) use ($id) {
return $d['id'] === $id;
}));
$multiplePossibilities = preparePossibilities($data);
$allTrees = [];
foreach ($multiplePossibilities as $possibility) {
if (empty($possibility['config'])) {
return [$possibility];
}
$config = $possibility['config'];
unset($possibility['config']);
$trees = [];
foreach ($config as $i => $and) {
$subTrees = getAllTrees($and['id']);
foreach ($subTrees as $subTree) {
$trees[$i][] = $subTree;
}
}
$trees = array_values($trees);
if (count($trees) === 1) {
foreach ($trees as $tree) {
foreach ($tree as $t) {
$newP = $possibility;
$newP['config'] = [];
$newP['config'][] = $t;
$allTrees[] = $newP;
}
}
} elseif (are_same($trees)) {
$newP = $possibility;
$newP['config'] = $trees;
$allTrees[] = $newP;
} else {
$newP = $possibility;
$newP['config'] = [];
foreach ($trees as $tree) {
if (count($tree) === 1) {
$newP['config'][] = $tree[0];
} else {
foreach ($tree as $t) {
$p3 = $newP;
$p3['config'][] = $t;
$allTrees[] = $p3;
}
}
}
}
}
return $allTrees;
}
foreach (getAllTrees('a') as $tree) {
var_dump(formatTree($tree));
}
好吧,如果我是你,我会开始分解问题,简化测试数据,然后让它变得更复杂。您还可以创建一个节点类,该类能够添加其他节点并打印其子节点。关于2f或1g等的计数。这只是一个选项数组,你可以做一个基本的for循环,不是吗?筛选所有选项。每次你添加另一个节点。谢谢你的回复,我会试试你的建议!我已经试着打破,但在某个时候,当更复杂的时候,我无法让它工作。。。但是我会尝试node类并在options上循环。如果我是你,我会开始解决这个问题,简化测试数据,然后随着时间的推移使它变得更复杂。您还可以创建一个节点类,该类能够添加其他节点并打印其子节点。关于2f或1g等的计数。这只是一个选项数组,你可以做一个基本的for循环,不是吗?筛选所有选项。每次你添加另一个节点。谢谢你的回复,我会试试你的建议!我已经试着打破,但在某个时候,当更复杂的时候,我无法让它工作。。。但我将尝试node类和循环选项