为递归数组中的每个元素设置id

时间:2014-10-13 14:13:29

标签: php recursion

我想为每个元素和sub以及sub的sub设置id或索引,依此类推

<?php

    $data = array(
        array(
            'title' => 'a',
            'children' => array(
                array(
                    'title' => 'a-a',
                    'children' => array(
                        array(
                            'title' => 'a-a-a',
                            'children' => array(

                            )
                        )                
                    )
                ),
                array(
                    'title' => 'a-b',
                    'children' => array(

                    )
                )                        
            )
        ),
        array(
            'title' => 'b',
            'children' => array(

            )
        )
    );

?>

我正在寻找与递归一起使用的PHP代码或函数来添加索引键和数字(desc)这样的输出

<?php

    $data = array(
        array(
            'index' => 1,
            'children' => array(
                array(
                    'index' => 2,
                    'children' => array(
                        array(
                            'index' => 3,
                            'children' => array(

                            )
                        )                
                    )
                ),
                array(
                    'index' => 4,
                    'children' => array(

                    )
                )                        
            )
        ),
        array(
            'index' => 5,
            'children' => array(

            )
        )
    );

?>

2 个答案:

答案 0 :(得分:2)

曾几何时,有一项研究得出的结论是,年轻的padawan程序员在成为绝地高级程序员的过程中面临的最大挑战是:

  

[...]有三个主要的语义障碍使新手命令式程序员绊倒。他们是:

     
      
  • 分配和顺序
  •   
  • 递归 / iteration
  •   
  • 并发
  •   

我第一次在Jeff Atwood的博客文章Separating Programming Sheep from Non-Programming Goats中遇到了这个理论,该论文基于科学论文:The camel has two humps (working title)

这是实现您想要的代码(减去仅{em>可视化步骤的echo次调用):

function addIndexRecursive(&$data) {
    static $index = 0;
    echo "The index is: $index" . PHP_EOL;

    foreach ($data as &$item) {
        $index++;
        echo "The index was incremented: {$index}" . PHP_EOL;

        $item = array('index' => $index) + $item;
        echo "Add the index to the item with title: {$item['title']}" . PHP_EOL;

        if (count($item['children']) > 0) {
            echo "This item has children so call the index function" . PHP_EOL;
            addIndexRecursive($item['children'], $index);
        // this else branch is only for illustration  purposes only
        } else {
            echo "There are no children therefore I stop" . PHP_EOL;
        }
    }
}

所以请稍微剖析一下。

首先要注意的是:我pass the array by reference。这只是一个品味问题,我更喜欢直接修改数组而不是构建另一个副本。

static $index将帮助我跟踪当前索引,并且会在遇到每个项目时递增。让我们看看这个static做了什么样的黑魔法(根据Variable scope):

  

静态变量仅存在于本地函数作用域中,但在程序执行离开此作用域时它不会丢失其值。

再次

foreach ($data as &$item)我希望元素通过引用传递,这样我就可以直接在循环中修改它们。

现在我们讨论了实现细节,让我们看看该函数的 back-trace 是什么:

addIndexRecursive was call and the index is: 0
The index was incremented: 1
Add the index to the item with title: a
This item has children so call the function
    addIndexRecursive was call and the index is: 1
    The index was incremented: 2
    Add the index to the item with title: a-a
    This item has children so call the function
        addIndexRecursive was call and the index is: 2
        The index was incremented: 3
        Add the index to the item with title: a-a-a
        There are no children therefore I stop
    The index was incremented: 4
    Add the index to the item with title: a-b
    There are no children therefore I stop
The index was incremented: 5
Add the index to the item with title: b
There are no children therefore I stop

你会继续遇到这类问题,所以越早掌握递归概念越好。

答案 1 :(得分:1)

这是“嵌套数组”的示例,其中各个数组需要:

1) an entry to be added: 'index' => <incrementing number> where there is a 'children' entry in the array.
2) an entry to be removed where: 'title' exists in the array.

由于数组可以“嵌套”,因此“递归”是处理“数据”数组的最合适方式。

我发现更容易修改数组“就地”而不是构建'output'数组。因此'数组引用'(&amp; $ arrayEntry)使用了很多。

我使用提供的测试数据并测试'required'数组和'indexed'数组在'结构'方面是相同的。

这是经过测试的代码:Windows XP上的PHP 5.3.18。的 Working code at: viper-7.com

完成工作的功能:

function addChildrenIndex(&$destData, &$idxNew)
{
    foreach($destData as $currentKey => &$currentValue) { // pass be reference so i can amend it

        if (is_array($currentValue)) { // ensure is 'children' array

            if (isset($currentValue['children'])) { // add the 'index' entry
                $currentValue['index'] = $idxNew;
                $idxNew++;
            }

            if (isset($currentValue['title'])) { // remove the 'title' entry!
                unset($currentValue['title']);
            }
            // as it is an array we 'recurse' around it - always...
            addChildrenIndex($currentValue, $idxNew);
        }
    }
}

驾驶密码:

$idxNew = 1;  // starting index.

// COPY the source data so i can test it later if required...
$indexedData = $data; // output array

addChildrenIndex($indexedData, $idxNew); // re-index the array 'in place'

// echo 'Required Array: <pre>';
// print_r($requiredData);
// echo '</pre>';

// echo 'OutputArray: <pre>';
// print_r($indexedData);
// echo '</pre>';

// test array structures to contain same entries...
var_dump($indexedData == $requiredData, 'ARE EQUAL?');

必需的测试数据:见问题

索引输出:

Array
(
    [0] => Array
        (
            [children] => Array
                (
                    [0] => Array
                        (
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [children] => Array
                                                (
                                                )

                                            [index] => 3
                                        )

                                )

                            [index] => 2
                        )

                    [1] => Array
                        (
                            [children] => Array
                                (
                                )

                            [index] => 4
                        )

                )

            [index] => 1
        )

    [1] => Array
        (
            [children] => Array
                (
                )

            [index] => 5
        )

)