php - 在 PHP 中创建具有给定深度、根和父级数量的子级的树结构
问题描述
我有一个用户,我将考虑我的树结构的根元素。之后,我有一组来自我的数据库的用户,我考虑了树的所有子元素。
树的构建需要包含以下决定树的宽度和深度的变量:
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 - 如何构建树结构列表? 但我似乎无法使其适应我的用例,因为我的数据库中没有父子关系。
这个 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 个子项和除根以外的任何其他元素的 1 个最大子项的变量):
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 个变量,如何创建此树结构?
解决方案
编辑:我看到最初的问题是寻找一个适用于 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);
推荐阅读
- sql - 从 spark 数据框或 sql 中选择具有偏好层次结构的多个记录
- java - XML 解析器中名称空间的工作和重要性
- mathjax - 动态加载 MathJax
- javascript - DevExtreme onLegendClick 阻止 onSeriesClick
- java - 使用服务帐户对 gmail 进行 OAuth2 身份验证
- json - 从查询结果生成 json
- python - 使用 pandas 分配绝对路径时出现语法错误
- java - 春天:'org.springframework.beans.factory.UnsatisfiedDependencyException'。创建具有名称的 bean 时出错
- node.js - 未捕获的 AssertionError:预期 404 等于 200
- log4j - WSO2IS:Log4j 1.2 安全漏洞