我的情况是我有一个由大约6,000个键/值对组成的数组结构。
数组的结构如下:
Array
(
[0] => Array
(
[parent] => parentA
[name] => child1
)
[1] => Array
(
[parent] => parentB
[name] => childC
)
[2] => Array
(
[parent] => parentA
[name] => child2
)
[3] => Array
(
[parent] => parentC
[name] => child3
)
[4] => Array
(
[parent] => child1
[name] => child4
)
[5] => Array
(
[parent] => child4
[name] => child5
)
从该数据源我试图将输出按到
A)我可以在以后的功能中使用的数组
B)一个表格显示,其中每一行将是一个完整的链,每列将更深。基本上,如果您考虑页面导航,这是一个面包屑显示,其中每个节点都在下一列。
我一直在玩这里的几种方法
1)在此堆栈溢出问题中使用递归函数:https://stackoverflow.com/a/2915920/997226,但是我无法修改它以使用父数据可以相同的数据。在他们的$ tree示例中,左手(键)值始终是唯一的。
我在他们的例子中理解他们的关键是孩子,价值(右手边)是父母,但是我仍然无法让这个为我工作,因为在我的数据中,两个人都有相同项目的倍数父母方面和儿童方面。 (想想一下文章可以包含在多个父类别中的复杂关系。
2)我已经尝试开始创建一个独特父元素的“基础数组”,然后创建一个递归函数来搜索“原始键值数组”,但这也不是很有用。
3)我尝试将数据保存在数据库中,因为我非常熟悉使用左/右值来访问/操作数据作为嵌套集,但我试图避免必须从中获取所有INSERT / SELECT数据库。
4)我尝试使用各种PHP Iterators类,因为我已成功使用它们来处理文件系统和构建文件/目录列表,所以我一直在玩RecursiveArrayIterator / ParentIterator / ArrayIterator,但不能似乎要弄清楚要使用的正确语法。
我知道递归可能不如使用这个大小的数据集的引用那么有效,但是它似乎提供了最大的灵活性,我似乎无法让它以递归方式正确迭代。
除此之外,我还试图更好地理解程序化递归的算法性质。
我通过其他人尝试做类似事情的代码示例阅读得越多,但是使用不同的数据结构我会变得更加困惑。
如果有人能帮我指出正确的方向,我们将不胜感激。
澄清说明
答案 0 :(得分:1)
**更新#2 - 我使用引用(不是递归)重新设计。这只需要一次通过数据。每个父级或子级都作为顶级项添加到数组(在本例中为$ a)(如果它尚不存在)。此顶级项的键是父级或子级的名称。该值是一个数组,其中包含对其子级顶级项的引用。此外,创建第二个数组($ p),仅引用第一个数组中的父项($ a)。在一次非常快速的通过中,发现了所有的关系。
守则(更新#2):
<?php
$tree_base = array(
array('parent' => 'parentA','name' => 'child1'),
array('parent' => 'parentB','name' => 'childC'),
array('parent' => 'parentA','name' => 'child2'),
array('parent' => 'parentC','name' => 'child3'),
array('parent' => 'child1','name' => 'child4'),
array( 'parent' => 'child4', 'name' => 'child5'),
array( 'parent' => 'DataSelect', 'name' => 'getBaseUri'),
array( 'parent' => 'getBaseUri', 'name' => 'getKbBaseURI')
);
$tree = parseTree($tree_base);
echo '<pre>'.print_r($tree, TRUE).'</pre>';
showresults($tree);
function parseTree($tree){
$a = array();
foreach ($tree as $item){
if (!isset($a[$item['name']])){
// add child to array of all elements
$a[$item['name']] = array();
}
if (!isset($a[$item['parent']])){
// add parent to array of all elements
$a[$item['parent']] = array();
// add reference to master list of parents
$p[$item['parent']] = &$a[$item['parent']];
}
if (!isset($a[$item['parent']][$item['name']])){
// add reference to child for this parent
$a[$item['parent']][$item['name']] = &$a[$item['name']];
}
}
return $p;
}
function showresults($tree, &$loop = array()){
if (is_array($tree) & count($tree) > 0){
echo "<table>";
echo "<tr>";
foreach ($tree as $key => $children){
// prevent endless recursion
if (!array_key_exists($key, $loop)){
$loop[$key] = null;
echo "<tr>";
echo "<td style='border:1px solid'>";
echo $key;
echo "<td style='border:1px solid'>";
showresults($children, $loop);
echo "</td>";
echo "</td>";
echo "</tr>";
}
}
echo "</tr>";
echo "</table>";
}
}
?>
输出(对于更新#2):
Array
(
[parentA] => Array
(
[child1] => Array
(
[child4] => Array
(
[child5] => Array
(
)
)
)
[child2] => Array
(
)
)
[parentB] => Array
(
[childC] => Array
(
)
)
[parentC] => Array
(
[child3] => Array
(
)
)
[DataSelect] => Array
(
[getBaseUri] => Array
(
[getKbBaseURI] => Array
(
)
)
)
)
**更新#1 - 我已修复代码以显示多级子级(以及您的新示例数组结构)。为了保持干净,我只使用生成的数组元素的键来存储父级和子级的名称。表输出变得更加复杂。我为每个父/子组使用了一行,其中第一列为父级,第二列为其子级。这也是递归的,因此包含子项的列可以在相同格式的新表中显示其子项(如果有)(查看比查找更容易)。
输出(对于更新#1):
Array
(
[parentA] => Array
(
[child1] => Array
(
[child4] => Array
(
[child5] =>
)
)
[child2] =>
)
[parentB] => Array
(
[childC] =>
)
[parentC] => Array
(
[child3] =>
)
)
代码(更新#1):
<?php
$array = array(
array('parent' => 'parentA',
'name' => 'child1'),
array('parent' => 'parentB',
'name' => 'childC'),
array('parent' => 'parentA',
'name' => 'child2'),
array('parent' => 'parentC',
'name' => 'child3'),
array('parent' => 'child1',
'name' => 'child4'),
array( 'parent' => 'child4',
'name' => 'child5')
);
// parse array into a hierarchical tree structure
$tree = parseTree($array);
// Show results
echo '<pre>';
print_r($tree);
echo '</pre>';
echo "<br>Table Format:";
showresults($tree);
function parseTree(& $tree, $root = null) {
$return = null;
// Traverse the tree and search for children of current parent
foreach ($tree as $key=> $item){
// A child is found
if ($item['parent'] == $root){
// append child into array of children & recurse for children of children
$return[$item['name']] = parseTree($tree, $item['name']);
// delete child so won't include again
unset ($tree[$key]);
}
elseif ($root == null) {
// top level parent - add to array
$return[$item['parent']] = parseTree($tree, $item['parent']);
// delete child so won't include again
unset ($tree[$key]);
}
}
return $return;
}
function showresults($tree){
if (is_array($tree)){
echo "<table>";
echo "<tr>";
foreach ($tree as $key => $children){
echo "<tr>";
echo "<td style='border:1px solid'>";
echo $key;
echo "<td style='border:1px solid'>";
showresults($children, true);
echo "</td>";
echo "</td>";
echo "</tr>";
}
echo "</tr>";
echo "</table>";
}
}
?>