@centropull

PHP Как преобразовать функцию рекурсии?

Имеем найденный на просторах пример:
// Массив
$tree = array(
    '1' => array(
        '1.1' => array(),
        '1.2' => array(),
        '1.3' => array(
            '1.3.1' => array(),
            '1.3.2' => array(
                '1.3.2.1' => array(),
                '1.3.2.2' => array(),
                '1.3.2.3' => array(),
            ),
            '1.3.3' => array(),
        ),
    ),
    '2' => array(
        '2.1' => array(),
        '2.2' => array(),
    ),
    // ...
);
 
// Функция
function parents($tree, $search_key, &$parents) {
    foreach ($tree as $key => $item) {
        if ($key == $search_key) {
            return true;
        }
        else if ($item && parents($item, $search_key, $parents)) {
            $parents[] = $key;
            return true;
        }
    }
    return false;
}
 
// Вызов
parents($tree, '1.3.2.2', $parents);
print_r($parents);
 
// Результат
Array
(
    [0] => 1.3.2
    [1] => 1.3
    [2] => 1
)


Как должна выглядеть функция, чтоб рекурсия происходила внутри функции, а не на саму функцию.
Есть предположение что внутри функции должен быть еще один цикл foreach.

// Функция
function parents($tree, $search_key) {
    // Код
}
 
// Вызов
$parents = parents($tree, '1.3.2.2');
print_r($parents);


Благодарю за помощь.
  • Вопрос задан
  • 462 просмотра
Решения вопроса 1
Immortal_pony
@Immortal_pony Куратор тега PHP
Как должна выглядеть функция, чтоб рекурсия происходила внутри функции, а не на саму функцию.

Рекурсия - это и есть вызов функции из нее же. Вы, конечно, можете создать функцию, которая будет вызывать рекурсивную функцию, но тогда функция с рекурсией никуда не денется.
С другой стороны, любую функцию можно переписать без использования рекурсии.
Например так:
function parents($tree, $childKey) {
    $parents = [];     
    $endOfTree = false;
    $minLevel = 1;
    $currentLevel = 1;
    $parentBranches = [];
    $branch = $tree;
    $branchKey = key($branch);
    $branchValue = current($branch);
    
    while (!$endOfTree) {      
        // Обработка текущего элемента
        if (strpos($childKey, $branchKey . ".") === 0 && $branchKey !== $childKey) {
            $parents[] = (string)$branchKey;
        }
        
        // Переключение ветки на внутренни уровень, если он есть
        if (is_array($branchValue) && !empty($branchValue)) {
            $currentLevel++;
            $parentBranches[] = $branch;
            $branch = $branchValue;                        
            $branchKey = key($branch);
            $branchValue = current($branchValue);
            continue;
        } 

        //  Переключение на следующий элемент
        $branchValue = next($branch);
        $branchKey = key($branch);
        
        // В случае, если следующего элемента нет, возврат на уровень выше или завершение цикла
        if ($branchValue === false) { 
            $branch = array_pop($parentBranches);
            $currentLevel--;
            
            // Возврат на уровень выше, если это возможно
            if ($currentLevel >= $minLevel) {
                $branchValue = next($branch);      
                $branchKey = key($branch);    
            // Завершение цикла, если уровень минимальный
            } else {
                $endOfTree = true;
            }
        }
    }
    
    // Смена направления массива и возвращение результата
    return array_reverse($parents);
}



// Проверка
parents($tree, '1.3.2.2'); 
/*
array(3) {
  [0]=>
  string(5) "1.3.2"
  [1]=>
  string(3) "1.3"
  [2]=>
  string(1) "1"
}
*/
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы