我有一个用户,我将考虑我的树结构的根元素。 之后,我从数据库中获得了一系列用户,这些用户考虑了树的所有子元素。
树的构建需要包含以下确定树的宽度和深度的变量:
Variable: MATCHES_TREE_MAX_DEPTH (eg: 3)
Variable: MATCHES_TREE_ROOT_MAX_CHILDREN_AMOUNT (eg: 2)
Variable: MATCHES_TREE_PARENT_MAX_CHILDREN_AMOUNT (eg: 1)
这意味着我想创建一个深度为3的树结构(这包括根元素,因此我想更深2级)。根元素有2个子元素,而任何子元素的子元素最多具有1个子元素。
这些项在我的用户数组中的顺序是我要在树中插入它们的顺序(我想先将它们插入广度而不是深度)。
我在SO上找到了以下通用函数:PHP - How to build tree structure list? 但是我似乎无法使其适应我的用例,因为我没有来自数据库的父子关系。
这个SO答案返回了一个看起来相似的数组,但是在将其重新设置为用例时遇到了问题: PHP generate a tree by specified depth and rules
示例数据如下:
根用户:
object(stdClass)[56]
public 'user_id' => string '1' (length=1)
public 'first_name' => string 'Dennis' (length=6)
其他用户(孩子):
array (size=3)
0 =>
object(stdClass)[57]
public 'user_id' => string '2' (length=2)
public 'first_name' => string 'Tom' (length=3)
public 'street' => string 'Teststreet' (length=10)
1 =>
object(stdClass)[58]
public 'user_id' => string '3' (length=2)
public 'first_name' => string 'Mary' (length=1)
public 'street' => string 'Maryland avenue' (length=15)
2 =>
object(stdClass)[59]
public 'user_id' => string '4' (length=2)
public 'first_name' => string 'Jeff' (length=4)
public 'street' => string 'Teststreet' (length=10)
我想用填充的示例来实现的树的示例(考虑了3个最大深度,2个root子节点和1个max子节点(除root以外的任何元素)的变量):
Array
(
[userid] => 1
[name] => "Dennis"
[matches] => Array
(
[0] => Array
(
[userid] => 2
[name] => "Tom"
[street] => "Teststreet"
[matches] => Array
(
[0] => Array
(
[userid] => 4
[name] => "Jeff"
[street] => "Teststreet"
[matches] = Array()
)
)
)
[1] => Array
(
[userid] => 3
[name] => "Mary"
[street] => "Maryland avenue"
[matches] => Array
(
)
)
)
)
在给定确定深度和子级的3个变量的情况下,如何创建这种树形结构?
答案 0 :(得分:1)
编辑:我看到原来的问题正在寻找与3个常数一起使用的解决方案。我已经添加了代码,因此可以定义常量并基于它们进行循环,但是我不确定我是否应该理解如何使用所有三个变量。特别是,根据您的描述, MATCHES_TREE_MAX_DEPTH 似乎不合适。您仅指示了两个级别的孩子,并指示我们应该跳过列表中的所有其他项目。如果您想要定义更多子级的代码,则需要更清楚地了解结构的增长方式。
鉴于在附加注释中对此问题描述的范围非常狭窄,似乎为解决该问题而烦恼循环很费力。这棵树不能有五个以上的元素,因此这样的迭代解决方案应该起作用:
// function to convert from list objects to the array we want as output
function new_obj($obj) {
$ret = array(
"userid" => $obj->user_id,
"name" => $obj->first_name
);
if (isset($obj->street)) {
$ret["street"] = $obj->street;
}
$ret["matches"] = [];
return $ret;
}
// INPUT DATA
$root = (object)["user_id" => "1", "first_name" => "Dennis"];
$children = [
(object)[
"user_id" => "2",
"first_name" => "Tom",
"street" => "Teststreet"
],
(object)[
"user_id" => "3",
"first_name" => "Mary",
"street" => "Maryland avenue"
],
(object)[
"user_id" => "4",
"first_name" => "Jeff",
"street" => "Teststreet"
],
(object)[
"user_id" => "5",
"first_name" => "Arthur",
"street" => "Teststreet"
]
];
$result1 = new_obj($root);
// an iterative solution, only works for one trivial set of values for the constants defined
// but also does provide some insight into a more general solution
if (isset($children[0])) {
$result1["matches"][0] = new_obj($children[0]);
}
if (isset($children[1])) {
$result1["matches"][1] = new_obj($children[1]);
}
if (isset($children[2])) {
$result1["matches"][0]["matches"][0] = new_obj($children[2]);
}
if (isset($children[3])) {
$result1["matches"][1]["matches"][0] = new_obj($children[3]);
}
print_r($result1);
如果要定义常量/变量以指定子限制,然后使用循环,请尝试使用与上面定义的相同的$ root和$ children变量。
// solution must use these constants:
define("MATCHES_TREE_MAX_DEPTH", 3);
define("MATCHES_TREE_ROOT_MAX_CHILDREN_AMOUNT", 2);
define("MATCHES_TREE_PARENT_MAX_CHILDREN_AMOUNT", 1);
$result2 = new_obj($root);
$i = 0;
while ($child = array_shift($children)) {
$result2["matches"][$i] = new_obj($child);
$i++;
if ($i >= MATCHES_TREE_ROOT_MAX_CHILDREN_AMOUNT) break;
}
$i = 0;
while ($grandchild = array_shift($children)) {
$child = $result2["matches"][$i];
if (count($child["matches"]) >= MATCHES_TREE_PARENT_MAX_CHILDREN_AMOUNT) {
// if we reach a child that has its max number of grandchildren, it's time to quit
break;
}
// otherwise, assign this child as a grandchild
$result2["matches"][$i]["matches"] = new_obj($grandchild);
// increment the counter and check if we cycle back to the first child of root
$i++;
if ($i >= count($result2["matches"])) {
$i = 0;
}
}
print_r($result2);