在PHP中创建递归数组

时间:2014-09-30 13:09:58

标签: php arrays recursion yii

我试图根据字符串的长度创建一个递归数组:字符串长度是节点的级别。这实际上是在Yii框架上构建一个树视图。这是一个例子......

我有一个字符串列表:

Array
(
    [0] => A
    [1] => C
    [2] => CC
    [3] => CCC
    [4] => P
    [5] => PP
    [6] => PPP
    [7] => PPPE
    [8] => PS
    [9] => PSA
)

我想对它们进行排序:

Array
(
    [0] => Array
        (
            [text] => A
        )

    [1] => Array
        (
            [text] => C
            [children] => Array
                (
                    [0] => Array
                        (
                            [text] => CC
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [text] => CCC
                                        )
                                )
                        )
                )
        )

    [2] => Array
        (
            [text] => P
            [children] => Array
                (
                    [0] => Array
                        (
                            [text] => PP
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [text] => PPP
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [text] => PPPE
                                                        )
                                                )
                                        )
                                )
                        )

                    [1] => Array
                        (
                            [text] => PS
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [text] => PSA
                                        )
                                )
                        )
                )
        )
)

我知道我已经找到了具有递归功能的东西,但我不知道该怎么做,尽管事实上我已经尝试了好几天...有人做了类似的事吗那个?非常感谢......

3 个答案:

答案 0 :(得分:2)

你的问题是一个奇特的问题,而且我无法帮助我解决这个问题。

我认为您不会发现递归会解决您的问题。原因是为了进行一些递归,你必须自己调用函数。当函数调用自身时,你可能已经对原始数组做了一些工作 - 使(几乎)必须通过引用传递数组的剩余部分。在您的情况下,问题是您希望以递归无法实现的方式重建阵列。 (至少在没有创建令人讨厌的if / else分支来处理你的条件的情况下。)

在你的情况下,我会建议你根据一些条件开展一个可以根据需要进行分类的课程。您的问题需要跟踪一些开销,以便根据需要重建阵列。您需要能够检查(但不限于)以下内容:

  1. 是否为text创建了索引。
  2. 是否为children创建了索引。
  3. 是否需要将评估的项目分配到textchildren
  4. 我是否在数组中处于正确的级别,还是需要向后遍历?
  5. 所有这些条件,加上您所需的分类要求,使这项任务最适合一个班级。你的类可以有各种字段来跟踪所有这些条件,并允许你正在使用的任何递归变得更有效。 (好消息是,如果你构建这样一个类并保持类内部的工作,它将很容易移植到其他项目。)

    无论如何,这是一个递归函数, 几乎 得到你想要的东西。

    <?php
    
    $source = array("A", "C", "CC", "CCC", "P", "PP", "PPP", "PPPE", "PS", "PSA");
    
    $rebuilt = array();
    function categorize(&$array)
    {
        $newArray = array();
        if(isset($array[0])) {
            $newArray["text"] = $array[0];
            array_shift($array);
            if(isset($array[0]) && (strlen($newArray["text"]) < strlen($array[0]))) {
                if(substr_compare($array[0], $newArray["text"], 0, strlen($newArray["text"])) == 0) {
                    $newArray["children"] = array(categorize($array));
                }
            }
        }
        return $newArray;
    }
    
    //Usage:
    
    $sorted = array();
    while(count($source) > 0) {
        $sorted[] = categorize($source);
    }
    print_r($sorted);
    
    ?>
    

    输出将是:

    Array
    (
        [0] => Array
            (
                [text] => A
            )
    
        [1] => Array
            (
                [text] => C
                [children] => Array
                    (
                        [0] => Array
                            (
                                [text] => CC
                                [children] => Array
                                    (
                                        [0] => Array
                                            (
                                                [text] => CCC
                                            )
    
                                    )
    
                            )
    
                    )
    
            )
    
        [2] => Array
            (
                [text] => P
                [children] => Array
                    (
                        [0] => Array
                            (
                                [text] => PP
                                [children] => Array
                                    (
                                        [0] => Array
                                            (
                                                [text] => PPP
                                                [children] => Array
                                                    (
                                                        [0] => Array
                                                            (
                                                                [text] => PPPE
                                                            )
    
                                                    )
    
                                            )
    
                                    )
    
                            )
    
                    )
    
            )
    
        [3] => Array
            (
                [text] => PS
                [children] => Array
                    (
                        [0] => Array
                            (
                                [text] => PSA
                            )
    
                    )
    
            )
    
    )
    

答案 1 :(得分:2)

这可以给你你想要的东西:

function &createNodeFromText(&$tree, $text)
{
    if(strlen($text) > 1) {
        //Make sure we have created the parent node(s) we need:
        $parent = &createNodeFromText($tree, substr($text, 0, -1));

        //Create a new tree level for the current node if needed:
        if(!isset($parent["children"])) {
            $parent["children"] = array();
        }
        $currentLevel = &$parent["children"];
    }
    else {
        //New root node:
        $currentLevel = &$tree;
    }

    //Look for the requested node..
    $nodeText = $text;
    $currentNode = null;
    for ($i = 0; $i < count($currentLevel); ++$i) {

        $node = &$currentLevel[$i];
        if($node["text"] === $nodeText)
        {
            $currentNode = &$node;
            break;
        }
    }
    //..and create a new one only if we have to:
    if($currentNode === null) {
        $currentNode = array("text" => $nodeText);
        $currentLevel[] = &$currentNode;
    }

    return $currentNode;
}


$source = array("A", "C", "CC", "CCC", "P", "PP", "PPP", "PPPE", "PS", "PSA");
$final = array();
foreach($source as $s) {
    createNodeFromText($final, $s);
}

print_r($final);

答案 2 :(得分:1)

<?php

     class ArrayRecursiver
    {
        private $baseArray = array();
        private $tmpArray = array();

        private function hasParentNode($node)
        {
            if(strlen($node) > 1)
                return true;
            else
                return false;

        }

        private function getParentNode($node)
        {
            return substr($node, 0, -1);
        }

        private function createNode($node, $existChild = null)
        {
            $_tmp = array("text" => $node);
            if (!empty($existChild))
                $_tmp = array("text"=> $node, "children" => $existChild);

            if ( $this->hasParentNode($node) )
            {
                return $this->createNode($this->getParentNode($node), $_tmp);
            }
            else
            {
                return $_tmp;
            }
        }

        public function setBase($a)
        {
            $_tmp = $a;
            usort($_tmp, function($a, $b) {
                if($a==$b) return 0;
                return $a < $b?1:-1;
            });

            $this->baseArray = $_tmp;
        }

        public function makeAWish()
        {
            $prev = null;
            foreach ($this->baseArray as $key => $node)
            {
                $_tmp = $this->createNode($node);
                    $this->tmpArray[]=  $_tmp;

            }
            return $this->tmpArray;
        }
    }// end class ArrayRecursiver

    $badArray = array(
        "A","C","CC","CCA","P","PP","PPP","PPPE","PS","PSA"
    );


        echo "<pre>";

        $worker = new ArrayRecursiver();
        $worker->setBase($badArray);
        print_r($worker->makeAWish());

        echo "</pre>";

它几乎可以满足你的需要;) 我说几乎;)你现在需要重建返回的数组,我希望这有帮助你