簡體   English   中英

將鍵值對的PHP數組轉換為分層嵌套樹結構

[英]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,但似乎無法想象使用正確的語法。

我知道遞歸可能不如使用這個大小的數據集的引用那么有效,但是它似乎提供了最大的靈活性,我似乎無法讓它以遞歸方式正確迭代。

除此之外,這個具體問題,我也試圖更好地理解程序遞歸的算法性質。

我通過其他人嘗試做類似事情的代碼示例閱讀的越多,但是使用不同的數據結構我會變得更加困惑。

如果有人能幫助我指出正確的方向,我們將不勝感激。

澄清說明

  1. 將有多個級別。
  2. 已經指出,數據結構可以被認為是有向無環圖並且完全有意義。

**更新#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM