【问题标题】:Iterate parent children without using recursive PHP在不使用递归 PHP 的情况下迭代父子节点
【发布时间】:2017-02-01 00:28:16
【问题描述】:

我有一个包含父子行的数据库表,一个父多个子,由字段“父”链接。

我知道如何在 PHP 中使用 recursive 函数循环和打印 jerarquy 结构,但是当我尝试使用单个循环代码重现它时,我无法以相同的格式呈现数据。此代码示例列出了数据库表中的所有项目,但未排序,它首先打印顶层,我想要经典:

  Top 1 >> Level 1 >> Level 2 >> Level 3
  Top 2 >> Level 1
  Top 3 >> Level 1 >> Level 2

  $parent = array();
  array_push($parent, 0);
  while(!empty($parent)){
    foreach($parent as $key => $mother){
      unset($parent[$key]);     
      $sql = "SELECT * FROM levels WHERE parent = " . $mother;
      $res = mysql_query($sql);
      while($row=mysqli_fetch_object($res)){
        print $row->name . "<br />";
        array_push($parent, $row->id);
      } // while
    } // foreach
  } // while

这段代码的结果是

前 1 名 前 2 名 前 3 名 1级 ...

【问题讨论】:

  • 在一个查询中选择您需要的所有数据然后对其进行处理不是更容易吗?
  • 在递归函数的情况下,我认为使用几个SELECT会容易得多。在任何情况下,您都可以考虑填充了与数据库中完全相同的结构的数组。您如何遍历它以以首选方式列出数据?递归很简单,求一个非递归的方式。

标签: php recursion iteration


【解决方案1】:

这里最大的问题是你为什么要以非递归方式?看到你有多个,而且似乎是一个不确定的子节点级别,这正是递归函数擅长的。

只使用简单的循环,您需要有与子级一样多的嵌套循环;或者,跟踪当前节点 ID、前一个节点 ID 和父节点 IDs(复数形式),然后使用它来确定是否要创建新叶子、退出叶子或留下在同一个。
基本上:

Same parent == same leaf
Different parent && parent == previous id, new leaf
Different parent { when (parentList[idx--] == parent) == change leaf to idx leaf.

在这两种方法中,后一种是迄今为止最具可扩展性的方法,并且只需要两个循环:一个用于所有元素的主循环,一个用于返回树的内部循环,直到找到正确的父 ID。基本上,通过使用递归函数来模拟你自然得到的一切。

我想评论的另一件事是您在循环中使用查询。这样做通常非常糟糕,因为它会成倍地增加代码的时间消耗。最好在一个查询中获取所有节点,按父节点和 ID 排序。这样您就不必额外等待 (n-1)*y 毫秒(或更多),其中 n 是记录数,y 是运行一次查询所需的时间。
如果查询需要 20 毫秒才能运行,并且您有 300 条记录,那么您将看到将近 6 秒的额外等待时间!仅仅是因为您将查询移动到循环内,而不是正确排序(或使用 JOIN)。
正如您所看到的,通过正确构建代码可以获得很多性能。不仅如此,它还会更容易阅读,从而维护您的代码。

总结:使用递归函数,因为这是它们的用途,并将您的查询移到循环之外。

【讨论】:

  • 只是单纯的兴趣。至于循环内的 SQL 查询,你是完全正确的。我这样做是为了不在庞大的数组中消耗 PHP 内存,但是在与我习惯的不同的其他场景中,你是对的,它会显着降低效率。
  • 很高兴我能帮上忙。能够帮助他人学习总是很高兴,尤其是当他们好奇并愿意这样做时。 :) 继续努力!
猜你喜欢
  • 2021-05-10
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2011-10-02
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多