【问题标题】:How do I transform this array into a multi-dimensional array via recursion?如何通过递归将此数组转换为多维数组?
【发布时间】:2012-06-10 23:43:20
【问题描述】:

所以我的示例输入是

$example_1 = Array (
    0 => Array (
        'category'     => 'body',
        'sub-category' => 'intro',
        'id'           => 'header',
        'copy'         => 'Hello',
    ),
    1 => Array (
        'category'     => 'body',
        'sub-category' => 'intro',
        'id'           => 'footer',
        'copy'         => 'Bye',
    ),
);

$example_2 = Array (
    0 => Array (
        'category'     => 'body',
        'sub-category' => 'intro',
        'sub-sub-category' => 'header',
        'sub-sub-child-category' => 'left',
        'id'           => 'title',
        'copy'         => 'Hello',
    ),
    1 => Array (
        'category'     => 'body',
        'sub-category' => 'intro',
        'sub-sub-category' => 'footer',
        'sub-sub-child-category' => 'right',
        'id'           => 'title',
        'copy'         => 'Bye',
    ),
);

我想把它变成

$example_output_1 = Array (
    'body' => Array (
        'intro' => Array (
            'header' => Array (
                'title' => 'Hello',
            ),
            'footer' => Array (
                'title' => 'Bye',
            ),
        ),
    ),
);

$example_output_2 = Array (
    'body' => Array (
        'intro' => Array (
            'header' => Array ( 
                'left' => Array (
                    'title' => 'Hello',
                ),
            ),
            'footer' => Array (
                'right' => Array (
                    'title' => 'Bye',
                )
            ),
        ),
    ),
);

注意数组的深度是动态的(它没有设置——只有当它点击“复制”时才表示数组的深度)。

我在尝试正确获取递归时遇到问题。我所拥有的基本但非常粗略的算法是 - 循环遍历行 - 循环遍历行的内容 - 当索引为“复制”时,最终值为当前值。 - 然后构建数组

我设法让它只处理数组的一行,但它非常混乱而且有点不完整,所以我觉得我真的需要从头开始。 更新:按要求附上令人尴尬的代码(不要尖叫!;p)

function buildArray($row, $start = true) {

    if ($start) {
        $result = array();
    }

    if ( ! is_array($row) ) {
        return $row;
    }

    // Get the first element of the array include its index
    $cellValue = null;
    $colId = null;
    foreach($row AS $index => $value) {
        $cellValue = $value;
        $colId = $index;
        break; 
    }

    // Reduce the array by one
    $tempRow = $row;
    $temp = array_shift($tempRow);

    if ($colId == 'copy') {
        $result[$cell] = buildArray($cellValue, $locale, false);
    } else {
      $result[$cell] = buildArray($tempRow, $locale, false);
    }

    return $result;
} 

任何帮助将不胜感激。

【问题讨论】:

  • 听起来很直接。你不能把你对算法的文字描述变成实际的foreach 循环吗?否则,这种看起来像 gimme teh codez 请求。我们想帮助您,而不是为您工作;)再试一次并发布结果。
  • 感谢您发布代码。别担心。与他人分享并获得反馈总是一种很好的学习体验。
  • 大部分递归性质可以使用array_merge_recursive解决,其余的都是尾递归的,因此可以迭代解决:)

标签: php recursion multidimensional-array


【解决方案1】:

这可以迭代解决,因为递归只会发生在函数的尾部。以下代码是简化。它在迭代旧数组的同时构建一个新的分层数组。

在转换每个条目后,它使用array_merge_recursive 合并。

function transform($a)
{
    // create new array and keep a reference to it
    $b = array(); $cur = &$b;
    foreach ($a as $key => $value) {
        if ('id' === $key) {
            // we're done, add value to the array built so far using id and copy
            $cur[$value] = $a['copy'];
            break;
        } else {
            // create one more level
            $cur[$value] = array();
            // and update the reference
            $cur = &$cur[$value];
        }
    }
    // all done
    return $b;
}

// $example_2 is your multi-dimensional array
$merged = call_user_func_array('array_merge_recursive', 
    array_map('transform', $example_2)
);

【讨论】:

  • 感谢所有回答的人。选择哪个是可接受的最佳答案是一个艰难的决定,因为两者都是可以接受的,但 StackOverflow 不允许 >1 答案。我选择了这个作为可接受的答案,因为@Jack 向我强调了我没有意识到存在的 array_merge_recursive 函数。
【解决方案2】:

应该很简单:

$originalArray = array(); // <-- should contain your values
$newArray = array();

foreach( $originalArray as $item )
{
    $category = $item['category'];
    $subcategory = $item['sub-category'];

    if ( empty( $newArray[$category] ) )
    {
        $newArray[$category] = array();
    }
    if ( empty( $newArray[$category][$subcategory] ) )
    {
        $newArray[$category][$subcategory] = array();
    }

    $newArray[$category][$subcategory][$item['id']] = $item['copy'];
}

在此处查看实际操作:http://codepad.viper-7.com/9bDiLP


更新:既然你已经指定了你需要无限递归,这里是一个镜头:

$originalArray = array(); // <-- Your values go here
$newArray = array();

foreach ( $originalArray as $item )
{
    $inception = &$newArray; // http://www.imdb.com/title/tt1375666/

    foreach ( $item as $key => $val )
    {
        if ( $key != 'id' )
        {
            if ( empty($inception[$val]) )
            {
                $inception[$val] = array();
            }
            $inception = &$inception[$val];
        }
        else
        {
            $inception[ $val ] = $item['copy'];
            break;
        }
    }
}

...这是演示:http://codepad.viper-7.com/F9hY7h

【讨论】:

  • 谢谢你,我忘了补充说这只是输入的一个例子,深度实际上可能是未知的(因此我为什么要尝试递归)
  • @MechaStorm - 更深的数组会保存什么?您可以将其添加到您的问题中吗?
  • 感谢所有回答的人。选择哪个是可接受的最佳答案是一个艰难的决定,因为两者都是可以接受的,但 StackOverflow 不允许 >1 答案。我选择了另一个作为可接受的答案,因为@Jack 向我强调了我没有意识到存在的 array_merge_recursive 函数。但我也想强调这也是另一个可接受的答案。
猜你喜欢
  • 2015-05-30
  • 1970-01-01
  • 2019-04-28
  • 2015-11-11
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 2019-04-03
  • 1970-01-01
相关资源
最近更新 更多