【发布时间】:2015-01-12 15:30:47
【问题描述】:
我在 MySQL 数据库中有一个表示遗传语言树的表。每行是一种语言,带有一个 ID 和一个父 ID;例如:
id | language | parent
-----+---------------------+--------
1 | Proto-Indo-European | NULL
6 | Celtic | 1
8 | Insular Celtic | 6
9 | Goidelic | 8
14 | Irish | 9
16 | Manx | 9
21 | British | 8
22 | Welsh | 21
109 | Germanic | 1
115 | West Germanic | 109
117 | Anglo-Saxon | 115
118 | Anglic | 117
119 | Old English | 118
我的目标是使用简单的递归 PHP 函数将这些行变成一个漂亮的嵌套 HTML 列表,在每种语言之后有聚合计数器,从而产生类似这样的结果(基于上面示例行中的语言):
- 原始印欧语 (11)
- 凯尔特人 (6)
- 岛屿凯尔特人 (5)
- 戈德利克 (2)
- 爱尔兰语
- 马恩岛
- 英式 (1)
- 威尔士语
- 日耳曼语 (4)
- 西日耳曼语 (3)
- 盎格鲁-撒克逊 (2)
- 英语 (1)
- 古英语
我有以下 PHP 函数(此处简化),它创建了一个具有正确结构的多维数组:
function select_languages_hierarchical($parent = NULL) {
global $db;
$branch = array();
$query = "SELECT * FROM languages WHERE parent = $parent";
if ($q = $db->query($query)) {
while ($row = $q->fetch_assoc()) {
$element['id'] = $row['id'];
$element['name'] = $row['language'];
$children = select_languages_hierarchical($row['id']);
if ($children) {
$element['children'] = $children;
}
$branch[] = $element;
}
}
return $branch;
}
这会生成一个与上面的嵌套列表匹配的数组,其中嵌套数组位于每个数组的 children 元素中。
但是,尽管在 SO 上绞尽脑汁、在谷歌上搜索并查看了大量的递归、聚合计数和数组计数问题,但我终其一生都无法找到创建计数器的方法描述每种语言的后代语言数量。
无论我做什么,无论我在哪里创建、修改和使用我的计数器变量,以及我尝试计数的任何事情(无论是每次迭代语言时执行一次ˋ$count++ˋ,执行一次ˋcount($children)ˋ等),当函数达到“更高”级别时,我总是会得到计数器未重置的结果,因此我会得到这样的列表:
- 原始印欧语 (12)
- 凯尔特人 (6)
- 岛屿凯尔特人 (5)
- 戈德利克 (2)
- 爱尔兰语
- 马恩岛
- 英式 (4)
- 威尔士语
- 日耳曼语 (9)
- 西日耳曼语 (12)
- 盎格鲁-撒克逊 (14)
- 英语 (15)
- 古英语
——或者类似的东西——数字和它们加起来的方式在我尝试的各种不同的实现中有所不同;但它们都有一个共同点,即计数器一直在增加,而从未被重置。或者,如果我确实尝试在某个时候重置它,它自然会在 每次 迭代时重置,给我留下:
- 原始印欧语 (2)
- 凯尔特人 (2)
- 岛屿凯尔特人 (1)
- 戈德利克 (2)
- 爱尔兰语
- 马恩岛
- 英式 (1)
- 威尔士语
- 日耳曼语 (1)
- 西日耳曼语 (1)
- 盎格鲁-撒克逊 (1)
- 英语 (1)
- 古英语
显然,逻辑不是我的强项。
有人可以通过建议一种方法来帮助我实现我正在寻找的那种“智能计数”,从而帮助我的大脑避免自发燃烧和/或内爆吗?
【问题讨论】:
-
你已经接近了。基本上更新您的数组,以便您在每个节点存储子计数和子信息。例如
$node['count'] = 3, $node['name'] = 'West Germanic', $node['children'] = array of child languages. -
@MarcB 这正是我想要做的。问题在于获取正确的数字(即您的示例中的
3)以存储在$element['countchildren']中(正如我在代码中一直调用的那样)。 -
当你进行递归调用时。基本上用您从递归调用收到的节点中存储的计数更新当前节点的子计数,例如
$curnode['count'] += $children['count']。问题是现在你只是在做$element['children'] = $children,它将取代你以前的递归调用。您需要合并结果。 -
@MarcB 恐怕我不太关注你。您能否在适当的位置发表您的评论,以便我准确地更新具有哪些值的节点?
-
投反对票的人是否愿意解释他们的投反对票(如果他们看到这个)?
标签: php recursion multidimensional-array count children