PHP Walk через многомерный массив с сохранением ключей
У меня есть многомерный массив, который я не могу знать глубину. Например, массив может выглядеть так:
$array = array(
1 => array(
5 => array(
3 => 'testvalue1'
)
),
2 => array(
6 => 'testvalue2'
),
3 => 'testvalue3',
4 => 'testvalue4',
);
С помощью этого массива я хочу создать оглавление. Это означает, что ключи должны быть сохранены, поскольку я использую их как "номера глав". Например, "testvalue1" находится в главе 1.5.3.
Теперь я хочу пройтись по массиву, сохранив все ключи - не используя array_walk_recursive, так как ключи, содержащие другой массив, отбрасываются (правильно?) И желательно не использовать вложенные циклы foreach с учетом скорости.
Любые предложения, как мне это сделать? Заранее спасибо.
PS: Для моего скрипта не имеет значения, являются ли ключи строками ("1" вместо 1) или целыми числами, если наличие строки в качестве ключа заставит array_walk_recursive сохранить их.
3 ответа
Вы можете перебирать свой массив с помощью стека, чтобы построить свой ток.
$stack = &$array;
$separator = '.';
$toc = array();
while ($stack) {
list($key, $value) = each($stack);
unset($stack[$key]);
if (is_array($value)) {
$build = array($key => ''); # numbering without a title.
foreach ($value as $subKey => $node)
$build[$key . $separator . $subKey] = $node;
$stack = $build + $stack;
continue;
}
$toc[$key] = $key. ' ' . $value;
}
print_r($toc);
Выход:
Array
(
[1] => 1
[1.5] => 1.5
[1.5.3] => 1.5.3 testvalue1
[2] => 2
[2.6] => 2.6 testvalue2
[3] => 3 testvalue3
[4] => 4 testvalue4
)
Вы можете дополнительно справиться с уровнем, если вам это нужно, но это не было ясно из вашего вопроса.
array_walk_recursive
не работает, потому что он не даст вам ключи родительского элемента (ов). Посмотрите также на этот связанный вопрос: прозрачно сгладьте массив, он имеет хороший ответ и полезен также для более общих случаев.
<?php
$td = array(1=>array(5=>array(3=>'testvalue1',array(6=>'testvalue2'))),2=>array(6=>'testvalue2',array(6=>'testvalue2',array(6=>'testvalue2'),array(6=>'testvalue2',array(6=>'testvalue2')))),3=>'testvalue3',4=>'testvalue4');
print_r($td);
$toc = '';
function TOC($arr,$ke='',$l=array()) {
if (is_array($arr)) {
if ($ke != '') array_push($l,$ke);
foreach($arr as $k => $v)
TOC($v,$k,$l);
}
else {
array_push($l,$ke);
$GLOBALS['toc'].=implode('.',$l)." = $arr\n";
}
}
toc($td);
echo "\n\n".$toc;
?>
Попробуй это:
<?php
$ar = array(
1 => array(
5 => array(
3 => 'testvalue1',
5 => 'test',
6 => array(
9 => 'testval 9'
)
),
8 => 'testvalue9'
),
2 => array(
6 => 'testvalue2',
7 => 'testvalue8',
2 => array(
6 => 'testvalue2',
7 => 'testvalue8'
),
),
3 => 'testvalue3',
4 => 'testvalue4'
);
function getNestedItems($input, $level = array()){
$output = array();
foreach($input as $key => $item){
$level[] = $key;
if(is_array($item)){
$output = (array)$output + (array)getNestedItems($item, $level);
} else {
$output[(string)implode('.', $level)] = $item;
}
array_pop($level);
}
return $output;
}
var_dump(getNestedItems($ar));