PHP Прогулка по многомерному массиву при сохранении ключей

У меня есть многомерный массив, о котором я не могу знать глубину. Например, массив может выглядеть следующим образом:

$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: Для моего script не имеет значения, являются ли клавиши строками ( "1" вместо 1) или целыми числами, если они содержат строки как ключ, сделают array_walk_recursive их сохраненными.

Ответ 1

Вы можете выполнить итерацию по вашему массиву с помощью стека, чтобы построить ваш 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 не работает, потому что он не даст вам ключей родительского элемента (ов). См. Также этот связанный вопрос: Прозрачно сгладить массив, он имеет хороший ответ и полезен и для более общих случаев.

Ответ 2

<?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;
?>

http://codepad.org/4l4385MZ

Ответ 3

Попробуйте следующее:

<?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));