2012-06-06 83 views
0

不知道我在做什么错这个递归函数。 我有一个网站树的数组,我正在寻找的页面可以是无限深的。 该功能经历了所有可能性,但有时在找到正确的“页面”时不会停止。PHP递归没有停止

阵列

$haystack = array(
    array("id" => 1,"parent" => 0,"route" => "home","children" => array()), 
    array("id" => 2,"parent" => 0,"route" => "news","children" => array()), 
    array("id" => 3,"parent" => 0,"route" => "photography","children" => array(
       array("id" => 6,"parent" => 3,"route" => "photography/portraits","children" => array()), 
       array("id" => 7,"parent" => 3,"route" => "photography/countries","children" => array()), 
       array("id" => 8,"parent" => 3,"route" => "photography/landscapes","children" => array(
           array("id" => 9,"parent" => 8,"route" => "photography/landscapes/city","children" => array()), 
           array("id" => 10,"parent" => 8,"route" => "photography/landscapes/wilderness","children" => array()) 
          ) 
       ) 
     ) 
    ), 
    array("id" => 4,"parent" => 0,"route" => "about","children" => array()), 
    array("id" => 5,"parent" => 0,"route" => "contact","children" => array()), 
); 

递归函数

function recurse($needle = -1, $haystack = NULL){ 
    $_tmp = array(); 

    foreach($haystack as $key => $item) 
    { 
     echo $needle ." === ". $item["id"] . "<br/>"; 

     if((string)$item["id"] === (string)$needle){ 
      echo "Found: " . $needle . "<br/><br/>"; 
      $_tmp = $item; 
      break; 
      //return $item; <-- this doesn't work either 
     } else { 
      $_tmp = recurse($needle, $item["children"]); 
     } 
    } 
    return $_tmp; 
} 

测试用例:

$test = recurse(3); 
print_r($test); 

$test = recurse(7); 
print_r($test); 

$test = recurse(9); 
print_r($test); 

最后测试输出:

9 === 1 
9 === 2 
9 === 4 
9 === 7 
9 === 8 
9 === 11 
9 === 12 
9 === 13 
9 === 14 
9 === 15 
9 === 3 
9 === 9 
Found: 9 <-- should stop here, but continues 

9 === 5 
9 === 6 
Array 
(
) 
+1

您是否试过'return $ item;'* without * break;'? – Hassan

+3

问题标题不应该是有趣的,但我一直在反复阅读和笑。 – rdlowrey

+0

选中此项。 http://stackoverflow.com/a/10777501/1420642这是为嵌套的评论,但它几乎是相同的 –

回答

1

这里有一个稍微修改的递归功能,修复你的问题:

function recurse($needle = -1, $haystack = NULL){ 
    static $_tmp = array(); 

    if (count($_tmp) == 0 && $haystack != NULL && count($haystack) > 0) { 
     foreach($haystack as $key => $item) { 
      if (count($_tmp) == 0) { 
       echo $needle ." === ". $item["id"] . "<br/>\n"; 

       if((string)$item["id"] === (string)$needle){ 
        echo "Found: " . $needle . "<br/>\n"; 
        $_tmp = $item; 
        break; 
       } elseif (!empty($item["children"])) { 
        echo "calling ". $item["id"]. ".children <br/>\n"; 
        $_tmp = recurse($needle, $item["children"]); 
       } 
      } 
     } 
    } 
    return $_tmp; 
} 

基本上它声明了一个静态变量$_tmp是被一次初始化,然后进行检查,处理循环只有$_tmp为空确保停止皮毛处理一次已找到。

Online working demo of above code

+0

我得到的价值回来了,但有没有办法阻止所有进程?您的测试输出显示它在找到针后继续递归。如果我有一个巨大的阵列,1000个左右的项目,如果我正在寻找某个东西,比如前10个,那么没有任何意义。另外,如果我可以在那个时候停止这个过程,那么我会无论如何返回的值。 – pioSko

+0

您可以通过在循环中对静态变量的大小进行另一次检查,使其更有效,如同在我上一次编辑中一样。在此处查看演示:g ideone.com/WXtNB – anubhava

+0

谢谢anubhava!工作:) – pioSko

3

它返回但在其他递归框架中继续。 例如,调用:1→2→3→4. 从4返回,但3(1→2→3)继续执行循环。

+0

是的,我知道,但我认为返回应该阻止它。我尝试了“休息2”,但我得到一个错误。我不想这个函数只是为了阻止一切:P – pioSko

+0

这不是一个好习惯,但是你可以传递一些初始设置为false的布尔变量,并在break之前将它设置为true。在循环开始之前检查它的值,如果它是真的,则返回。 – Ruben

1

你可以沿着阵列只有你没有找到你是什么水平,像这样:

function recurse($needle = -1, $haystack = NULL){ 
    $_tmp = array(); 

    foreach($haystack as $key => $item) 
    { 
     echo $needle ." === ". $item["id"] . "<br/>"; 

     if((string)$item["id"] === (string)$needle){ 
      echo "Found: " . $needle . "<br/><br/>"; 
      $_tmp = $item; 
      break; 
      //return $item; <-- this doesn't work either 
     } 
    } 
    if (empty($_tmp)) 
     foreach($haystack as $key => $item) 
     { 
      $_tmp = recurse($needle, $item["children"]); 
     } 

    return $_tmp; 
}