У меня есть многомерный массив, о котором я не могу знать глубину. Например, массив может выглядеть так:
$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.
Вы можете выполнять итерацию по вашему массиву с помощью стека для создания вашего тока.
$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);
с$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));