操纵多维数组的结构

时间:2009-04-20 21:24:21

标签: php arrays

这实际上是我已经解决的问题,但我怀疑可能有更好的解决方案。我有一个嵌套数组,它基本上代表了一个类别树中所有节点的列表(没有特定的顺序):

Array(
    [0] => Array(
        [Category] => Array(
            [id] => 49
            [name] => Poster
        )
        [Child] => Array()
    )
    [1] => Array(
        [Category] => Array(
            [id] => 48
            [name] => Sticker
        )
        [Child] => Array()
    )
    [2] => Array(
        [Category] => Array(
            [id] => 46
            [name] => Hat
        )
        [Child] => Array()
    )
    [3] => Array(
        [Category] => Array(
            [id] => 45
            [name] => Hoodie
        )
        [Child] => Array()
    )
)

你会注意到$node['Child']在所有实例中都是一个空数组。这是因为我已经使用array_filter()来过滤掉所有非叶子节点。不过,我最终想要的是拥有叶节点的一维数组,如下所示:

Array(
    [49] => Poster
    [48] => Sticker
    [46] => Hat
    [45] => Hoodie
)

那么将第一个数组转换为第二个数组的最优雅方式是什么?

或者,您也可以从叶节点和非叶节点的数组开始,并尝试修剪数组并重组它。非叶节点的示例如下:

[7] => Array(
    [Category] => Array(
        [id] => 36
        [name] => Merch
    )
    [Child] => Array(
        [0] => Array(
            [id] => 49
            [name] => Poster
        )
        [1] => Array(
            [id] => 48
            [name] => Sticker
        )
        [2] => Array(
            [id] => 40
            [name] => Apparel
        )
    )
)

最后,我正在使用CakePHP,因此也可以使用CakePHP的Set类。

2 个答案:

答案 0 :(得分:4)

优雅?定义优雅。我认为有些人会把这变成一场高尔夫比赛,而不是简单地做一些有意义的事情,并且对于后来绊倒这些代码的人来说很明显:

$cats = array();
foreach($categories as $c) {
    $cats[$c['Category']['id']] = $c['Category']['name'];
}

我怀疑这就是你所拥有的,在这种情况下,我建议你拍拍自己,继续前进。

答案 1 :(得分:1)

这个答案无论如何都不是“优雅”,但我认为它可能属于“聪明”范畴。 (注意:聪明的解决方案并不总是“好”的解决方案)

preg_match_all( "/\"name\";s:\d+:\"(.*?)\"/i", serialize( $arr ), $matches );

print_r( $matches[1] );

老实说,递归迭代是清晰度的最佳选择,即使它不是非常有效或简洁。

$arr = array(
    "0" => array(
        "Category" => array(
            "id" => 49
            ,"name" => Poster
        )
        ,"Child" => array()
    )
    ,"1" => array(
        "Category" => array(
            "id" => 48
            ,"name" => Sticker
        )
        ,"Child" => array()
    )
    ,"2" => array(
        "Category" => array(
            "id" => 46
            ,"name" => Hat
        )
        ,"Child" => array()
    )
    ,"3" => array(
        "Category" => array(
            "id" => 45
            ,"name" => Hoodie
        )
        ,"Child" => array(
            "0" => array(
                "id" => 49
                ,"name" => Poster
            )
            ,"1" => array(
                "id" => 48
                ,"name" => Sticker
            )
            ,"2" => array(
                "id" => 40
                ,"name" => Apparel
            )
        )
    )
);

findNames( $arr, $names );
echo '<pre>';
print_r( $names );
echo '</pre>';

function findNames( $source, &$out )
{
    foreach ( $source as $value )
    {
        if ( isset( $value['name'] ) )
        {
            //  Assumes that if $value['name'] exists, $value['id'] must also exist
            $out[$value['id']] = $value['name'];
            continue;
        }
        if ( is_array( $value ) )
        {
            findNames( $value, &$out );
        }
    }
}