在PHP中创建递归数组


Creating a recursive array in PHP

我正试图根据字符串的长度创建一个递归数组:字符串长度是节点的级别。这实际上是在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
                                        )
                                )
                        )
                )
        )
)

我知道我必须用递归函数来解决一些问题,但我不知道怎么做,尽管我已经尝试了好几天了。。。有人做了那样的事吗?非常感谢。。。

这应该会给你想要的:

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);

你的问题很特别,我忍不住想弄明白。

我认为你不会发现递归能解决你的问题。原因是为了进行一些递归,必须让函数调用本身。当函数调用自身时,您可能已经对原始数组做了一些工作——这使得(几乎)有必要通过引用传递数组的剩余部分。这种情况下的问题是,您希望以递归无法实现的方式重建数组。(至少在不造成if/else分支机构处理您的情况的恶劣混乱的情况下。)

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

  1. 是否已为text创建索引
  2. 是否已为children创建索引
  3. 是否需要将正在评估的项目分配给textchildren
  4. 我是在数组中处于正确的级别,还是需要向后遍历

所有这些条件,再加上您想要的排序要求,使此任务最适合一个类。您的类可以有各种字段来跟踪所有这些条件,并允许您使用的任何递归变得更加有效。(好消息是,如果你构建这样一个类并将内部工作保持在该类中,它将很容易移植到其他项目。)

无论如何,这里有一个递归函数,它将几乎得到您想要的。

<?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
                        )
                )
        )
)
<?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>";

它几乎是做你需要的事;)我说差不多;)你现在需要重建返回的数组,我希望这能帮助你