我对如何解决这个问题感到有点失落,我怀疑foreach
不是正确的答案,我知道array_walk()
和{{1}的存在但是,我没有使用任何一个的实际经验,所以我可以在正确的方向上做一点指针。 (如果它对答案有任何影响,我正在使用PHP 7.1.9。)
来源数据
我有一个包含父/子对象树的单维数组。您可以假设树具有未知和可变的嵌套深度。一个基本示例如下所示:
RecursiveArrayIterator
所需的输出
最终目标是输出HTML列表(即$sampleParent=array("id"=>101,"level"=>1,"parent_id"=>1,"name"=>"parent","otherparam"=>"bar");
$sampleChildD1=array("id"=>234,"level"=>2,"parent_id"=>101,"name"=>"level1","otherparam"=>"bar");
$sampleChildD2=array("id"=>499,"level"=>3,"parent_id"=>234,"name"=>"level2","otherparam"=>"bar");
$sampleTree=array($sampleParent,$sampleChildD1,$sampleChildD2);
),每个父级一个列表。通过嵌套<ul><li></li></ul>
标记实现嵌套。所以对于我上面的例子:
<ul>
答案 0 :(得分:1)
我可以建议以OOP方式执行此操作吗? 我创建了一个包含属性和子列表的对象。如果您愿意,还可以添加从子项到其父项的链接,如此示例
class TreeNode {
// string
public $name;
// integer
public $id;
// TreeNode
public $parent;
// TreeNode[]
public $children;
}
使用这种结构,使用foreach迭代它应该非常简单。
答案 1 :(得分:1)
您可以延长RecursiveArrayIterator
:
class AdjacencyListIterator extends RecursiveArrayIterator
{
private $adjacencyList;
public function __construct(
array $adjacencyList,
array $array = null,
$flags = 0
) {
$this->adjacencyList = $adjacencyList;
$array = !is_null($array)
? $array
: array_filter($adjacencyList, function ($node) {
return is_null($node['parent_id']);
});
parent::__construct($array, $flags);
}
private $children;
public function hasChildren()
{
$children = array_filter($this->adjacencyList, function ($node) {
return $node['parent_id'] === $this->current()['id'];
});
if (!empty($children)) {
$this->children = $children;
return true;
}
return false;
}
public function getChildren()
{
return new static($this->adjacencyList, $this->children);
}
}
然后你可以使用RecursiveIteratorIterator
遍历这个迭代器,或者你可以扩展前者用HTML自动装饰树:
class UlRecursiveIteratorIterator extends RecursiveIteratorIterator
{
public function beginIteration()
{
echo '<ul>', PHP_EOL;
}
public function endIteration()
{
echo '</ul>', PHP_EOL;
}
public function beginChildren()
{
echo str_repeat("\t", $this->getDepth()), '<ul>', PHP_EOL;
}
public function endChildren()
{
echo str_repeat("\t", $this->getDepth()), '</ul>', PHP_EOL;
echo str_repeat("\t", $this->getDepth()), '</li>', PHP_EOL;
}
}
拥有这两个类,你可以像这样迭代你的树:
$iterator = new UlRecursiveIteratorIterator(
new AdjacencyListIterator($sampleTree),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $leaf) {
echo str_repeat("\t", $iterator->getDepth() + 1);
echo '<li>', '<a href="#">', $leaf['name'], '</a>';
echo $iterator->hasChildren() ? '' : '</li>', PHP_EOL;
}
这是working demo。
请注意,此处使用的str_repeat
和PHP_EOL
仅用于演示目的,应在现实代码中删除。