我基本上是尝试从表示树结构的多维数组构建一个html ul / li嵌套列表。
以下代码工作正常,但我想改进它:
我需要一种方法来跟踪递归级别,这样我就可以将不同的类应用到不同的级别,为生成的输出添加缩进等。
function buildTree($tree_array, $display_field, $children_field, $class='', $id='') {
echo "<ul>\n";
foreach ($tree_array as $row) {
echo "<li>\n";
echo $row[$display_field] . "\n";
if (isset($row[$children_field])) {
$this->buildTree($row[$children_field]);
}
echo "</li>\n";
}
echo "</ul>\n";
}
$ tree_array如下所示:
Array
(
[0] => Array
(
[category_id] => 1
[category_name] => calculatoare
[parent_id] => 0
[children] => Array
(
[0] => Array
(
[category_id] => 4
[category_name] => placi de baza
[parent_id] => 1
)
[1] => Array
(
[category_id] => 5
[category_name] => carcase
[parent_id] => 1
[children] => Array
(
[0] => Array
(
[category_id] => 6
[category_name] => midi-tower
[parent_id] => 5
)
)
)
)
)
[1] => Array
(
[category_id] => 2
[category_name] => electronice
[parent_id] => 0
)
[2] => Array
(
[category_id] => 3
[category_name] => carti
[parent_id] => 0
)
)
我已将此标记为家庭作业,因为我希望将此作为一个机会来改善我对递归的理解(差),所以,我会感谢能够指导我解决问题的答案,而不是提供完整的答案。工作实例:))
答案 0 :(得分:8)
Quick'n'dirty方法(请参阅下面的“扰流器”块):
在函数声明中添加一个额外的变量$recursionDepth
,默认为0。
在每次后续递归中,使用$recursionDepth + 1
调用您的函数。
由于函数变量对于函数的相应实例仅是“可见的”(作用域),因此最终会得到当前迭代深度的指示符。
此外,您的功能第12行
$this->buildTree();
并不认为它会起作用 - 原因是你没有将变量传递给下一个buildTree实例。
它可能应该是这样的:
$this->buildTree($row[$children_field], $display_field, $children_field, $class, $id)
以下是我为您的代码所做的更改,以实现您的目标:
function buildTree($tree_array, $display_field, $children_field, $class='', $id='', $recursionDepth = 0, $maxDepth = false)
{
if ($maxDepth && ($recursionDepth == $maxDepth)) return;
echo "<ul>\n";
foreach ($tree_array as $row)
{
echo "<li>\n";
echo $row[$display_field] . "\n";
if (isset($row[$children_field]))
$this->buildTree($row[$children_field], $display_field, $children_field, $class, $id, $recursionDepth + 1, $maxDepth);
echo "</li>\n";
}
echo "</ul>\n";
}
答案 1 :(得分:7)
你正在使你的生活变得比它需要的更困难。为方便起见,SPL提供了多个iterators。使用RecursiveArrayIterator
class可以轻松遍历多维数组。它不仅允许您处理任何级别深度数组,而且还可以跟踪深度。
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array)
);
for($iterator; $iterator->valid(); $iterator->next())
{
printf(
"Key: %s Value: %s Depth: %s\n",
$iterator->key(),
$iterator->current(),
$iterator->getDepth()
);
}
正如您所看到的,有一个方法getDepth()
将始终告诉您当前的迭代深度。这是在递归迭代器中迭代子节点所需的RecursiveIteratorIterator
方法。
如果您需要影响迭代开始时或访问子项时发生的事情,请查看我对Multidimensional array iteration的回答,该回答显示了将多维数组的值包装成自定义RecursiveIteratorIterator
的自定义{{1}} xml元素并按当前迭代的深度缩进它们(这对于适应ul / li元素应该是微不足道的。)
另请参阅Wikipedia Article about Iterators进行一般性介绍。
答案 2 :(得分:-1)
public virtual int GetLevelById(int id)
{
int i = GetParentById(id);
if (i == 0)
return 1;
else
return (1 + GetLevelById(i));
}
public virtual int GetParentById(int t) { var ret = this._list.FirstOrDefault((f)=&gt; f.Id == t); if(ret!= null) return ret.ParentId; 返回-1; }