Convert a series of parent-child relationships into a hierarchical tree?

前端 未结 11 1930
[愿得一人]
[愿得一人] 2020-11-22 07:04

I have a bunch of name-parentname pairs, that I\'d like to turn into as few heirarchical tree structures as possible. So for example, these could be the pairings:

         


        
11条回答
  •  臣服心动
    2020-11-22 07:35

    This requires a very basic recursive function to parse the child/parent pairs to a tree structure and another recursive function to print it out. Only one function would suffice but here's two for clarity (a combined function can be found at the end of this answer).

    First initialize the array of child/parent pairs:

    $tree = array(
        'H' => 'G',
        'F' => 'G',
        'G' => 'D',
        'E' => 'D',
        'A' => 'E',
        'B' => 'C',
        'C' => 'E',
        'D' => null
    );
    

    Then the function that parses that array into a hierarchical tree structure:

    function parseTree($tree, $root = null) {
        $return = array();
        # Traverse the tree and search for direct children of the root
        foreach($tree as $child => $parent) {
            # A direct child is found
            if($parent == $root) {
                # Remove item from tree (we don't need to traverse this again)
                unset($tree[$child]);
                # Append the child into result array and parse its children
                $return[] = array(
                    'name' => $child,
                    'children' => parseTree($tree, $child)
                );
            }
        }
        return empty($return) ? null : $return;    
    }
    

    And a function that traverses that tree to print out an unordered list:

    function printTree($tree) {
        if(!is_null($tree) && count($tree) > 0) {
            echo '
      '; foreach($tree as $node) { echo '
    • '.$node['name']; printTree($node['children']); echo '
    • '; } echo '
    '; } }

    And the actual usage:

    $result = parseTree($tree);
    printTree($result);
    

    Here's the contents of $result:

    Array(
        [0] => Array(
            [name] => D
            [children] => Array(
                [0] => Array(
                    [name] => G
                    [children] => Array(
                        [0] => Array(
                            [name] => H
                            [children] => NULL
                        )
                        [1] => Array(
                            [name] => F
                            [children] => NULL
                        )
                    )
                )
                [1] => Array(
                    [name] => E
                    [children] => Array(
                        [0] => Array(
                            [name] => A
                            [children] => NULL
                        )
                        [1] => Array(
                            [name] => C
                            [children] => Array(
                                [0] => Array(
                                    [name] => B
                                    [children] => NULL
                                )
                            )
                        )
                    )
                )
            )
        )
    )
    

    If you want a bit more efficiency, you can combine those functions into one and reduce the number of iterations made:

    function parseAndPrintTree($root, $tree) {
        $return = array();
        if(!is_null($tree) && count($tree) > 0) {
            echo '
      '; foreach($tree as $child => $parent) { if($parent == $root) { unset($tree[$child]); echo '
    • '.$child; parseAndPrintTree($child, $tree); echo '
    • '; } } echo '
    '; } }

    You'll only save 8 iterations on a dataset as small as this but on bigger sets it could make a difference.

提交回复
热议问题