PHP функция «возврат» не возвращает значение

1

У меня есть алгоритм, чтобы найти все уникальные комбинации множества foods. Если какая-либо из комбинаций соответствует нашему calories value тогда она должна возвращать значение true.

Вот мой подход:

<?php

$food = [
    ['a', 70],
    ['b', 5],
    ['c', 20],
    ['d', 10]
];

function eat($calories, $food, $k = 0, $p = []) {

    for ($i=$k; $i < count($food); $i++) { 

        $r = array_merge($p, [$i]);

        $c = 0;
        foreach ($r as $j) {
            $c += $food[$j][1];
        }

        if ($c == $calories) {
            echo "success";
            return true;
        }

        eat($calories, $food, $i+1, $r);
    }
}

var_dump(eat(100, $food));

?>

Возникает вопрос: почему этот код выводит "успех", но не возвращает true?

Вот онлайн-исполнение:

http://codepad.viper-7.com/PnTEKo

  • 3
    Ваша функция вызывает себя рекурсивно, но никогда не передает предыдущие возвращаемые значения обратно.
  • 0
    Кто написал этот код тогда? (Расширение вашего вопроса сложностью алгоритма и вопрос об альтернативах немного широки). Исправление действительно зависит от того, как оно должно себя вести. По крайней мере, сохраните предыдущий $success = eat(…); результат рекурсии. Либо верните преждевременно, когда истина, либо оставьте его до окончания цикла, а затем return его.
Теги:
algorithm

3 ответа

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

Исходная функция, которую вы вызываете, никогда не возвращает true, последующее funtion, которое вызывается, возвращает true для своего "родителя", но это истинное значение никогда не возвращается исходному вызывающему. Исправление будет следующим:

if (eat($calories, $food, $i+1, $r)) {
     return true;
}

Это проверяет, что возвращает рекурсивная функция, и если ее значение true, возвращается true

1

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

Здесь вам кажется, что вам нужно только выполнить один успешный вызов, после чего функция должна быть прервана. Таким образом, вы можете проверить успех, и если это произошло, верните true, чтобы предотвратить дальнейшую работу функции, и сообщите вызывающему абоненту (это может быть первый вызов или любые другие вызовы в рекурсии), что вызов был успешным.

<?php

$food = [
    ['a', 70],
    ['b', 5],
    ['c', 20],
    ['d', 10]
];

function eat($calories, $food, $k = 0, $p = []) {

    for ($i=$k; $i < count($food); $i++) { 

        $r = array_merge($p, [$i]);

        $c = 0;
        foreach ($r as $j) {
            $c += $food[$j][1];
        }

        if ($c == $calories) {
            echo "success";
            return true;
        }

        if(eat($calories, $food, $i+1, $r))
            return true;
    }
}

var_dump(eat(100, $food));

?>
  • 3
    Это может ответить на вопрос, но вы не объясните, что вы сделали. Так что этот ответ не очень полезен для будущих читателей
  • 0
    Я отредактировал это и объяснил немного.
1

Немного другой подход к рекурсивной функции массива будет заключаться в использовании встроенного функции arrayIterator.

        $food = array(
            'a'=> 70,
            'b'=> 5,
            'c'=> 20,
            'd'=> 10,
            'e'=> 99
        );

        function eat( $calories, $food, $p=array() ){
            $a = new ArrayObject( array_merge( $food, $p ) );
            $iterator = $a->getIterator();
            while( $iterator->valid() ) {
                if( $iterator->current()==$calories ) {
                    echo 'success: key='.$iterator->key().' value='.$iterator->current();
                    return true;
                }
                $iterator->next();
            }
            return false;
        }

        eat( 120, $food, array( 'banana'=>500,'apple'=>120 ) );

Ещё вопросы

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