[英]Converting a PHP array of key value pairs to a hierarchical nested tree structure
我有一種情況,我有一個由大約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,但似乎無法想象使用正確的語法。
我知道遞歸可能不如使用這個大小的數據集的引用那么有效,但是它似乎提供了最大的靈活性,我似乎無法讓它以遞歸方式正確迭代。
除此之外,這個具體問題,我也試圖更好地理解程序遞歸的算法性質。
我通過其他人嘗試做類似事情的代碼示例閱讀的越多,但是使用不同的數據結構我會變得更加困惑。
如果有人能幫助我指出正確的方向,我們將不勝感激。
澄清說明
**更新#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>";
}
}
?>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.