【问题标题】:Return inside PHP recursive function在 PHP 递归函数内部返回
【发布时间】:2020-09-05 21:29:22
【问题描述】:

我正在编写一个 PHP 递归函数来使用它们的值从数组中获取数据。所以这是我正在尝试构建的功能:

  function test($menu) {

    $url = "test.com/accounts/overview/";

    foreach($menu as $data) {

      if( is_array($data) and array_key_exists("t_link", $data) and $data["t_link"] === $url ) {

        return $data["t_icon"]; 

      } else if(is_array($data)) {

        test($data);

      }
    }
  }

echo test($menu);

第一个条件仅在我的数组中一次为真,return 必须返回值并终止函数,不是吗?但为什么它注意到回报?另外,如果我使用echo $data["t_icon"]; 而不是return $data["t_icon"];,它会显示正确的结果:fa fa-book

这是我试图根据t_link 值获取t_icon 值的数组。条件是如果t_link 值具有test.com/accounts/overview/,那么它将返回fa fa-book

$menu = array ();
$menu["Dashboard"] = array (
    "t_link"    => "test.com",
    "t_icon"    => "fa fa-dashboard"
  );
  $menu["Accounts"] = array (
    "t_link"    => "test.com/accounts",
    "t_icon"    => "fa fa-books"
  );
  $menu["Accounts"]["Overview"] = array (
    "t_link"    => "test.com/accounts/overview/",
    "t_icon"    => "fa fa-book"  <<-- This value I want to get
  );

我搜索了很多并得到了这个,我应该在第二个条件中返回函数,就像这样return test($data);。但它也不起作用。谢谢。

【问题讨论】:

  • 没有返回它运行函数但不返回任何东西。你想返回一个结果。您可能还有其他错误,请尝试使用调试器或添加日志记录。
  • 旁注:递归很酷。真的。特别是对于编译器。然而,函数调用在 php 中非常慢,并且循环要快得多 - 即使在 C 中也是如此。更不用说内存需求和嵌套函数限制(不太糟糕)。因此,除非你真的必须解决它的递归问题,否则最好使用结构良好的数组。
  • 谢谢@DavidHlavati先生,其实它是一个菜单数组。
  • @DaveS,其他错误?可以举个例子吗?
  • @bestprogrammerintheworld,如果不使用递归就可以得到期望值。我想要基于t_link 值的t_icon 值。

标签: php recursion


【解决方案1】:

因为你在函数内部调用了一个函数,所以你必须返回函数的值,这里是解决方法:(在test($data);之前添加了“return”)

 function test($menu) {

    $url = "test.com/accounts/overview/";

    foreach($menu as $data) {

      if( is_array($data) and array_key_exists("t_link", $data) and $data["t_link"] == $url ) {
        return $data["t_icon"]; 
      } else if(isset($data["Overview"])) {
        return test($data);
      }
    }
  }

另外,所有这三种情况,它们都是数组,所以 return test($data); 将停止 foreach 然后 $menu["Accounts"]["Overview"] 将永远不会被检查。

【讨论】:

  • 谢谢您,先生,请检查我的最后一行问题。我也试过你的方法。但是失败了。
  • @RoyalHarun 因为使用 return 会在 $menu["Dashboard"] 停止 foreach 而 echo 不会,你的逻辑有问题,而不是代码
  • 它如何在$menu["Dashboard"] 上退出,而它具有此条件$data["t_link"] === $url。好的没问题。你能告诉我修复方法吗?
  • 不是一个理想的解决方案。数组只是一个例子。 $menu["Accounts"]["Overview"] 可以是$menu["Accounts"]["Create"]$menu["Accounts"]["Other"] 所以这样......
  • @RoyalHarun 我之所以这么说是因为你的逻辑,我只是​​可以告诉你哪里出了问题,而我不知道你的数据可能是什么,在这种情况下你必须找到最好的逻辑,所以秒调用 test() 不会破坏 foreach 循环。
【解决方案2】:

您的代码无法正常工作,因为函数应该总是有一个返回值 - 在 recursion 中它是必需的

function test($menu) {

    $url = "test.com/accounts/overview/";

    foreach($menu as $data) {

      if( is_array($data) && 
      isset($data["t_link"]) && 
      $data["t_link"] === $url ) {        
          return $data["t_icon"]; 
      } 
      else if (is_array($data)) {
          $result = test($data); //Get result back from function

          //If it's NOT NULL call the function again (test($data))
          //
          //(down below returns null when looped through 
          //everything recursively)
          //
          if ($result !== null) { 
              return $result;
          }
      }

    }

    return null;
}

这是实现 OOP 风格的另一种方法:

这个解决方案背后的想法是创建一个两级数组(不多也不少于 nr 个级别)并从该新数组中获取数据。

class Searcher {
    private $new_arr = array();
    private $icon = '';

    //array_walk_recursive goes through your array recursively
    //and calls the getdata-method in the class. This method creates
    //a new array with strings (not arrays) from supplied $array ($menu in your case)
    public function __construct($array, $search_url) {
        array_walk_recursive($array, array($this, 'getdata'));     
        $key = array_search($search_url, $this->new_arr['t_link']);
        $this->icon = $this->new_arr['t_icon'][$key];
    }

    public function geticon() {
        return $this->icon;
    }

    public function getdata($item, $key) {
        if (!is_array($item)) {
            $this->new_arr[$key][] = $item;    
        }        
    }

}

//Implementation (usage) of above class
$search = new Searcher($menu, 'test.com/accounts/overview/');
$icon = $search->geticon();
echo 'ICON=' . $icon; //Would echo out 'fa fa-book'

进一步说明:

根据您的$menu - 数组,该类将创建一个像这样的数组 ($this-&gt;new_arr):

Array
(
    [t_link] => Array
        (
            [0] => test.com
            [1] => test.com/accounts
            [2] => test.com/accounts/overview/
        )

    [t_icon] => Array
        (
            [0] => fa fa-dashboard
            [1] => fa fa-books
            [2] => fa fa-book
        )

)

新数组中的所有键都相互关联。这是在getdata() 方法中使用$this-&gt;new_arr[$key][] = $item; 设置的。这是基于数组中 t_link-keys 和 t_icon-keys 的数量必须相等的事实。

因为:

$this->new_arr[0]['t_link'] is related to $this->new_arr[0]['t_icon'];
$this->new_arr[1]['t_link'] is related to $this->new_arr[1]['t_icon'];
$this->new_arr[2]['t_link'] is related to $this->new_arr[2]['t_icon'];
etc.. (not more in your example)

当有这个代码时:

$key = array_search($search_url, $this->new_arr['t_link']);

如果您向 test.com/accounts/overview/

提供了 $search_url,它将提供密钥 2

因此:

$this->icon = $this->new_arr['t_icon'][$key];

设置为 fa fa-book

【讨论】:

  • 谢谢@bestprogrammerintheworld,看起来你已经尝试了最好的方法来解决我的问题。我用另一种方式解决了我的问题。但我还是不明白,为什么我上面的代码不起作用?因为,第一个条件只成立一次,返回必须终止函数,不是吗?
  • 我已经更新了答案,并解释了为什么您的代码没有按预期工作。
  • 谢谢先生。你真的很棒。
猜你喜欢
  • 2013-09-21
  • 2012-03-11
  • 2015-04-27
  • 2018-02-21
  • 2018-01-04
  • 2011-05-23
  • 2021-03-02
  • 2021-08-14
  • 1970-01-01
相关资源
最近更新 更多