我有一个二维PHP数组,我需要将其转换为树。每个内部数组中的“path”值是当前节点的枚举路径。 (我从Bill Karwin关于SQL Antipatterns的书中得到了这个想法)。
所以,我开始的数组看起来像这样:
array(
[1] => array('name' => 'Animals', 'path' => '1/'),
[2] => array('name' => 'Birds', 'path' => '1/3/'),
[3] => array('name' => 'Cockatoos', 'path' => '1/3/5/'),
[4] => array('name' => 'Fish', 'path' => '1/2/'),
[5] => array('name' => 'Kookaburras', 'path' => '1/3/4/')
)
正如您可能已经收集的那样,外部数组的索引是没有意义的。我只是在'name'上按字母顺序排列内部数组,PHP在外部数组上分配了数字索引。
就'path'值而言,每个路径的最后一个段是节点的伪id,即Animals是节点1,Birds是节点3.你可以看到完整路径描述了路径到给定节点,例如'凤头鹦鹉'是'Birds'的父级,它是'动物'的父母。
我想保留节点的字母顺序,但要按父节点对它们进行分组。换句话说,我想要一个看起来像这样的数组(按照它的自然顺序):
[1] => 'Animals'
[1][3] => 'Birds'
[1][3][5] => 'Cockatoos'
[1][3][4] => 'Kookaburras'
[1][2] => 'Fish'
我计划以递归方式迭代这个以打印树的可视化表示。
在尝试从一种类型的数组转换到另一种类型时,我的方法使用了递归,变量变量和正则表达式,但我一直在路障中运行。
此外,是否存在我应该考虑的SPL数据结构或迭代器?
非常感谢!
编辑:对不起,应该提到树的深度是可变的。上面的例子有三个层次,但实际上会有更多层次。金
答案 0 :(得分:2)
由于使用了Eval()函数(代表求值),无论树的深度如何,这都可行。但是字母表上的排序还没有正常工作。因为父数组的索引保持不变,所以它会混淆。至少你可以建造一棵树:)
<?php
$a = array(
array('name' => 'Animals', 'path' => '1/'),
array('name' => 'Birds', 'path' => '1/3/'),
array('name' => 'Eagles', 'path' => '1/3/3/'),
array('name' => 'Cockatoos', 'path' => '1/3/5/'),
array('name' => 'Fish', 'path' => '1/2/'),
array('name' => 'Kookaburras', 'path' => '1/3/4/')
);
Iterate($a);
$tree = Iterate($a);
var_dump($tree);
OneLevelDeeper($tree);
var_dump($tree);
function Iterate($ChildArray)
{
$TreeArray;
foreach($ChildArray as $Key => $Value)
{
//echo $Key.': '.$Value['name']."\r\n";
$exp = explode('/', $Value['path']);
$path;
foreach($exp as $int)
{
if($int != "")
{
$path[] = $int;
}
}
//Using Eval() function of PHP
$BuildSourceToEvaluate = '$TreeArray';
for($i=0; $i<(count($path)-1); $i++)
{
$BuildSourceToEvaluate .= '[$path['.$i.']]';
}
$BuildSourceToEvaluate .= '[] = $Value[\'name\'];';
echo $BuildSourceToEvaluate."\r\n";
Eval($BuildSourceToEvaluate);
//print_r($path);
/*
switch(count($path))
{
case 0:
break;
case 1:
$TreeArray[] = $Value['name'];
//$TreeArray[$path[0]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
//$TreeArray[$path[0]][] = $Value['name']; //Use this for non-unique tree paths
break;
case 2:
$TreeArray[$path[0]][] = $Value['name'];
//$TreeArray[$path[0]][$path[1]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
//$TreeArray[$path[0]][$path[1]][] = $Value['name']; //Use this for non-unique tree paths
break;
case 3:
$TreeArray[$path[0]][$path[1]][] = $Value['name'];
//$TreeArray[$path[0]][$path[1]][$path[2]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
//$TreeArray[$path[0]][$path[1]][$path[2]][] = $Value['name']; //Use this for non-unique tree paths
break;
}
*/
unset($path);
}
return $TreeArray;
}
function OneLevelDeeper(&$a)
{
sort($a);
foreach($a as $Key => $Value)
{
if(is_array($Value))
{
sort($a[$Key]);
OneLevelDeeper($a[$Key]);
}
}
}
?>