我有一个多级数组。级别(子阵列)的数量是未知的。它可能只有两个,但也可能是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的对象
将原始Array(和所有子数组)转换为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
的噱头所以输出将是一个正常的数组?
P.S:我知道,有array_walk()
但它不是一个选项
更新:我应该提一下,关于获得正确结果的问题不。我知道,自定义recursiv函数(也许array_walk_recursive
())可以解决问题。
它更多地关于SPL RecursiveIterators 作为可能的解决方案。我只是想知道自己,为什么它与strClass
es一起工作,为什么不使用常规数组。
来自obeve的示例数组不是真正的用例。正如您可能猜到的那样,实际的用例是来自DB的数据的数组(有时超过600行)。其中一些有子阵列。我唯一知道的是应该修改的键(通过给定的规则)。 效果是主要标准
答案 0 :(得分: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
答案 1 :(得分: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);
答案 2 :(得分: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);
}
}
}
}