1

我有一个多级数组。级别(子阵列)的数量是未知的。它可能只有两个,也可能是 5 个。我唯一知道的 - 每个级别都有某些(已知的)键。

让我们考虑以下示例:

Array
(
    [number] => 21
    [otherkey] => value
    [sub] => Array
        (
            [count] => 
            [number] => 29
            [some] => thing
            [range] => Array
                (
                   ...
                )

            [sub] => Array
                (
                    [count] => 1
                    [number] => 16
                    [key] => value
                    [date] => 2013-07-25
                    [sub] => Array
                        (
                            [count] => 0
                            [number] => 4
                            [key] => value
                            [sub] => Array
                                (
                                    [count] => 1
                                    [number] => 24
                                    [key] => value
                                    [sub] => last
                                )

                        )

                )

        )

)

我的目标是遍历所有'number'键并创建像“偶数”或“奇数”这样的文本,结果应该保存在number_str每个级别的自己的键(比如)下

所以修改后的数组应该是这样的:

 Array
    (
        [number] => 21
        [otherkey] => value
        [sub] => Array
            (
                [count] => 
                [number] => 29
                [some] => thing
                [range] => Array
                    (
                     ...
                    )
                [sub] => Array
                    (
                        [count] => 1
                        [number] => 16
                        [key] => value
                        [date] => 2013-07-25
                        [sub] => Array
                            (
                                [count] => 0
                                [number] => 4
                                [key] => value
                                [sub] => Array
                                    (
                                        [count] => 1
                                        [number] => 24
                                        [key] => value
                                        [sub] => last
                                        [number_str] => even //new key
                                    )
                                [number_str] => even //new key

                            )
                        [number_str] => even //new key

                    )
                [number_str] => odd //new key

            )
        [number_str] => odd //new key
    )

所以我尝试使用 RecursiveIteratorIterator

$rai = new RecursiveArrayIterator($data);
$rii = new RecursiveIteratorIterator($rai);

foreach ($rii as $idx => $level) {
    if($idx === 'number')
    {
        $str = ($level % 2) ? 'odd' : 'even';
        $rii->offsetSet('number_str', $str);
    }
}

但它没有奏效。 所以我找到了一种“解决方法”。似乎可以,如果每个子数组都是 stdClass 的对象,我期望什么

将原始数组(和所有子数组)转换为 stdClass

$data = json_encode(json_decode($data)); // ..dirty gimmick. Possible performance killer ?

$rai = new RecursiveArrayIterator($data);
$rii = new RecursiveIteratorIterator($rai);

foreach ($rii as $idx => $level) {
    //same logic as above...
}

var_dump($rai);

现在看起来我希望得到结果,唯一的问题是,所有子级别现在都是 stdClass 的实例

在线代码-> http://ideone.com/PIiZOX

问题有没有办法获得相同的结果,但没有json_decode/的噱头,json_encode所以输出将是一个正常的 Array ?

PS:我知道,有,array_walk()但它不是一个选项

更新:我应该提到问题在于获得正确的结果。我知道,那个自定义递归函数(也许array_walk_recursive是 ())可以解决问题。它更多地是关于 SPLs RecursiveIterators作为可能的解决方案。我只是想知道自己,为什么它可以与strClasses 一起使用,为什么不与常规 Array 一起使用。

obeve 的示例 Array 并不是真正的用例。您可能会猜到,真正的用例是包含来自 DB 的数据的数组(有时超过 600 行)。其中一些具有子阵列。我唯一知道的是应该修改的键(通过给定的规则)。性能是主要标准

4

3 回答 3

1

尝试使用自定义递归函数:

function addEvenOrOdd(&$array) {
    $array['number_str'] = ($array['number'] % 2) ? 'odd' : 'even';
    ksort($array);
    if(isset($array['sub']) && is_array($array['sub'])) {
        addEvenOrOdd($array['sub']);
    }
}
addEvenOrOdd($yourarray);

在这里看到它的工作:http: //codepad.viper-7.com/vBc42b

于 2013-07-25T19:59:22.663 回答
1

我认为不需要使用 RecursiveArrayIterator,简单的递归函数就足够了。希望这会有所帮助:

function iterate_recursive( &$target_arr ){
    $val = 'odd';
    if( $target_arr[ 'number' ] % 2 == 0 ){
        $val = 'even';
    }
    $target_arr[ 'number_str' ] = $val;

    if( array_key_exists( 'sub', $target_arr ) and is_array($target_arr['sub'])){
        iterate_recursive( $target_arr[ 'sub' ] );
    }
}

$dta_arr = Array
    (
    'number' => 21,
    'otherkey' => 'value',
    'sub' => Array
        (
        'count' => 123,
        'number' => 29,
        'some' => 'thing',
        'range' => Array
            (
            'stub' => False,
        ),
        'sub' => Array
            (
            'count' => 1,
            'number' => 16,
            'key' => 'value',
            'date' => 2013 - 07 - 25,
            'sub' => Array
                (
                'count' => 0,
                'number' => 4,
                'key' => 'value',
                'sub' => Array
                    (
                    'count' => 1,
                    'number' => 24,
                    'key' => 'value',
                    'sub' => 'thing',
                )
            ),
        ),
    ),
);


iterate_recursive( $dta_arr );
print_r($dta_arr);
于 2013-07-25T20:00:48.490 回答
1
function even_or_odd(&$arr){
    if(is_array($arr)){
        if (isset($arr['number'])){
            if ($arr['number']%2 == 1){
                $arr['number_str'] = 'odd';
            } else {
                $arr['number_str'] = 'even';
            }
        }
        foreach( $arr as $key => &$val ){
            if(is_array($val)){
                self::even_or_odd($val);
            }
        }
    }
}
于 2013-07-25T20:08:16.717 回答