【问题标题】:php array recursionphp数组递归
【发布时间】:2010-09-23 09:02:28
【问题描述】:

我有一个这样的数组:

Array ( 
[0] => Array ( [id] => 1000 [enroller_id] => 1005) 

[1] => Array ( [id] => 1005 [enroller_id] =>) 

[2] => Array ( [id] => 1101 [enroller_id] => 1000 ) 

[3] => Array ( [id] => 1111 [enroller_id] => 1000 ) 
)

我想像这样创建层次结构数组:

Array(
[1005] => Array(
               [1000] => Array(
                              [1101] => ...
                              [1111] => ...
                              )
               )
)

你能帮帮我吗?我认为这是一个递归。

【问题讨论】:

    标签: php arrays recursion


    【解决方案1】:

    这将做你想做的事,除了它没有将第一个元素 (1005) 放入数组中:

    function create_array($number, $data)
    {
        $result = array();
        foreach ($data as $row)
        {
            if ($row['enroller_id'] == $number)
            {
                $result[$row['id']] = create_array($row['id'], $data);
            }
        }
        return $result;
    }
    
    print_r(create_array(1005, $data));
    

    输出:

    Array
    (
        [1000] => Array
            (
                [1101] => Array ()
                [1111] => Array ()
            )
    )
    

    【讨论】:

    • 谢谢。这是理想的解决方案!
    • 我们如何神奇地知道 1005?它不应该出现在结果中吗?
    • 1005 应该换成null,然后就可以了。通常情况下,递归很简单,但会导致过多的迭代。
    • +1,很好的递归现在我可以轻松地制作动态嵌套数组了。
    【解决方案2】:
    //$paths is an array of references, in which _every_ item will sit at 'root'
    //level, but also as a reference as a child to it's parent.
    
    //initialize location of parentless / root items:
    $paths = array('N'=>array());
    
    foreach($items as $item){
        //$target is the parent-id, or 'N' if we are a root node
        $target = isset($item['enroller_id']) && !empty($item['enroller_id']) ? $item['enroller_id'] :'N';
    
        //if the parent is not yet in the paths array, make an entry for it
        if(!isset($paths[$target]))      $paths[$target] = array();
    
        //if this item is not yet in the array (the previous statement could  
        //already have inserted it, make an array(
        if(!isset($paths[$item['id']]))  $paths[$item['id']] = array();
    
        //add the current item as a reference to it's parent
        $paths[$target][$item['id']] =  &$paths[$item['id']];
    
        //Setting it as a reference has this consequence:
        //   when adding an item to the $paths[$id] array, it will 
        //   automatically be added to $paths[$parent][$id], as 
        //   both $paths[$id] & $paths[$parent][$id] point to the same
        //   location in memory.
        //   This goes to infinite depth: if $foo is a child of $id, and you
        //   add a node to it, it will be in
        //   $paths[$foo]               = array($child);
        //   $paths[$id][[$foo]         = array($child);
        //   $paths[$parent][$id][$foo] = array($child);
        //
        //   Altering an item at any location in paths / the tree will alter it anywhere
        //   in the paths / tree, unsetting it anywhere only unset the data at that location, 
        //   other locations will still have the same data (and the data will keep 
        //   existing until the last reference is unset())
    
    }
    //we are only interested in the 'root' nodes (all other nodes should be subnodes
    //in this tree
    $tree = $paths['N'];
    //remove all unused references in the $paths array
    //do remember to do this: cleaning up references is important
    unset($paths);
    //tree is now an array of 'normal' values (i.e. only 1 reference to each datapoint exists
    var_dump($tree);
    

    不要忘记unset 路径:如果您不采取适当的措施,引用真的会让您难以追踪错误。

    【讨论】:

    • 它只是在每次迭代时链接当前节点及其父节点。一开始,您只有两个孤立节点。最终它们连接在一起,直到你得到最后一棵树。唯一的副作用是无根节点将被默默忽略,但这并不是算法的真正错误。
    • 在解决方案中添加了 cmets 以获得解释。 @Alexander.Plutov:愿意告诉我为什么吗?没有数据重复,只有一个循环,非常高效,最后没有引用。作为额外的奖励,项目的顺序无关紧要:您可以在输入中早于父项有一个子项,并且它仍然有效。
    • 不是那么明确。虽然这个解决方案很难理解,但它只在数组中循环一次。如果你有一棵大树,这比递归解决方案要快得多。
    • 拥有快速应用程序的最佳方法是使用适当的算法。这是我想到的第一个解决方案。看起来几乎是微不足道的......
    • 恕我直言,如果一个人不知道参考是什么,这只是不是“明确的”。遗憾的是,PHP 程序员并非总是如此,但我认为他们应该了解这些。不了解语言的基础知识并不是我个人改变答案的理由。是的,编写清晰易读的代码,并且可以采取轻微的性能损失来使代码更清晰和可维护,但在我看来,情况并非如此。
    猜你喜欢
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 2012-04-19
    • 2017-07-19
    • 2012-09-16
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多