В рекурсивной функции PHP, как я могу проверить, что это последняя итерация? - PullRequest
0 голосов
/ 11 октября 2019

У меня запущена и работает эта рекурсивная функция:

function my_function($a, $b, $level=0){


    $items = get_some_items($a, $b);

    $fh = fopen($fpath, 'a+');

    foreach($items as $item){
        fwrite($fh, "Some info related to $item");

        if( /* $item has something special */ ){

            my_function($a, $item, $level++);
        }
    }


    if( /* we a re at the last recursion */ ){
        //do something extra special;
        //e.g. fwrite($fh, "This is the end of the file");
    }


    fclose($fh);

}

С этим я могу сказать, какая итерация является первым запуском. Я также могу запустить nth на любом уровне.

Мой вопрос: я бы хотел сделать что-то особенное во время самого последнего запуска. Есть ли способ аккуратно этого добиться?

Ответы [ 3 ]

1 голос
/ 11 октября 2019

Просто проверьте, находитесь ли вы на листовом узле:

function my_function($a, $b, $level=0){
    $items = get_some_items($a, $b);
    if ($items) {
        foreach($items as $item){
            if( /* $item has something special */ ){
                my_function($a, $item, $level++);
            }
        }
    } else {
        /* we are at the last recursion */ 
        do_something_extra_special();
    }
}
1 голос
/ 11 октября 2019

Вы можете добавить новый параметр в конце, который возвращает true, только если номер элемента, на котором вы находитесь, совпадает с общим количеством элементов.

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

function my_function($a, $b, $level=0,$isLast=false){
    if($isLast){
        // Do something special on last item
    }
    $items = get_some_items($a, $b);    
    $total = count($items);
    $c=0;
    foreach($items as $item){
        $c++;
        my_function($a, $item, $level++,($c==$total));
    }

    // Additional check maybe to see if the first ever call is also the last?
    if($total==0 && $level<1){
        // Do something special on last item?
        // This could be at the top in the same IF statement
        // as the $isLast check (preferred) if things were moved around.
    }
}
0 голосов
/ 12 октября 2019

Ваш $level странным образом передается как $level++, который будет увеличиваться каждый раз в цикле foreach. Обычно, когда вы хотите иметь индикатор уровня в рекурсивном вызове функции, все вызовы подпоследовательности получат индикатор уровня текущего уровня + 1.

Если это так, то ваша первая глубина рекурсии всегда будет иметь $level из 0. Вы можете просто проверить $level и узнать, является ли это концом основного цикла в вашем самом внешнем вызове.

function my_function($a, $b, $level=0){


    $items = get_some_items($a, $b);

    $fh = fopen($fpath, 'a+');

    foreach($items as $item){
        fwrite($fh, "Some info related to $item");

        if( /* $item has something special */ ){

            my_function($a, $item, $level+1); // changed $level++ to $level+1
        }
    }


    if ($level === 0) { // check if it is the outermost call
        //do something extra special;
        //e.g. fwrite($fh, "This is the end of the file");
    }


    fclose($fh);

}
...