Функция с foreach неожиданно сохраняет значение переменной

1

Я пытаюсь захватить и распечатать все пути от корня до листа во вложенном массиве PHP. Так, например, если это мой массив:

$tree = array(
    "A" => "w",
    "B" => array("x" => array("y", "z"))
)

Я хочу, чтобы в качестве вывода:

Array
(
    [0] => Aw
    [1] => Bxy
    [2] => Bxz
)

Здесь моя функция в настоящее время:

function traverse($input, $myPath) {
    global $allPaths;
    if(is_array($input)) {
        foreach($input as $k => $v) {
            if(!is_int($k)) $myPath .= $k;
            traverse($v, $myPath);
        }
    } else {
        $myPath .= $input;
        $allPaths[] = $myPath;
    }
}

Когда я запускаю этот код:

$allPaths = array();
echo "<pre>";
traverse($tree, "");
print_r($allPaths);
echo "</pre>";

Вывод:

Array
(
    [0] => Aw
    [1] => ABxy
    [2] => ABxz
)

Это почти правильно, но по какой-то причине A сохраняется, когда он достигает части "B", а не сбрасывается, как я ожидал.

Я re- и re- прочитал код и пробовал каждое сообщение для отладки, о котором я могу думать, и до сих пор не понимаю, что происходит. Я уверен, что это либо что-то основное (возможно, настолько, что, если я еще не видел его, я никогда не буду), или я просто не понимаю, как работает переменная область.

Теги:
scope
arrays
foreach

1 ответ

1
Лучший ответ

Первый вызов функции выполняется над массивом верхнего уровня, поэтому ключи верхнего уровня всегда добавляются.

Чтобы исправить, передайте копию $myPath с $k добавленным к рекурсивным вызовам, вместо того, чтобы напрямую присоединяться к $myPath:

function traverse($input, $myPath) {
    global $allPaths;
    if(is_array($input)) {
        foreach($input as $k => $v) {
            if(!is_int($k)){
                traverse($v, $myPath . $k);
            }else{
                traverse($v, $myPath);
            }
        }
    } else {
        $myPath .= $input;
        $allPaths[] = $myPath;
    }
}
  • 1
    Спасибо! И таким образом я могу сделать это на более короткую строку, используя traverse ($ v, $ myPath. (Is_int ($ k)? "": $ K));
  • 0
    Да что бы хорошо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню