从父类中获取数组中的子项列表,而不使用PHP进行递归

时间:2012-04-03 15:23:20

标签: php arrays tree

我有一种情况,我已经获取并操纵SQL数据到一个数组和一个树。我试图不惜一切代价避免递归,因为它过去一直困扰着我。

我有一系列带有Parent_IDs的元素,我希望能够获得他们所有子女和子女的列表。它不应该像通过其他方式(从数组到嵌套树)一样复杂,我使用引用没有问题,但由于某种原因我被大脑冻结......

任何帮助表示感谢。

我有两种可能格式的数据,因为我已经操作过了。可以使用哪个最适合输入。这是我拥有的两个数组的结构(print_r):

Array
(
    [202735] => Array
        (
            [ID] => 202735
            [text] => aaafdf
            [Parent] => 
        )

    [202737] => Array
        (
            [ID] => 202737
            [text] => Filho 2
            [Parent] => 202735
        )

    [202733] => Array
        (
            [ID] => 202733
            [text] => Neto 1
            [Parent] => 202731
        )

    [202739] => Array
        (
            [ID] => 202739
            [text] => Neto 2
            [Parent] => 202737
        )

)

Array
(
    [0] => Array
        (
            [ID] => 202735
            [text] => aaafdf
            [Parent] => 
            [children] => Array
                (
                    [0] => Array
                        (
                            [ID] => 202737
                            [text] => Filho 2
                            [Parent] => 202735
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [ID] => 202739
                                            [text] => Neto 2
                                            [Parent] => 202737
                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [ID] => 202733
            [text] => Neto 1
            [Parent] => 202731
        )

)

所需的输出格式: (第一级父母=>所有子女和孙子女)

array(202731=>array(202735));
array(202735=>array(202737,202739));

或类似...理想情况下,我将这个函数包装在像ListChildren($ InitialParent)这样的函数中,并从这样的函数返回所有子元素...调用ListChildren(0)或(null)将列出所有元素和所有元素潜艇...

(出于本练习的目的,可以忽略其他数组元素)

OBS:数组中的一些数据丢失了......即202735以上的类别,即202731,但这仅仅是因为我限制了我复制的数据...基本上我可以有一个平面数组与父ids,或者"树"嵌套子元素作为源的数组。

3 个答案:

答案 0 :(得分:2)

我最终得到了这个。谢谢你的帮助,最后我恢复了递归代码。我将监视它的性能,虽然我认为只是在PHP层内它不会成为一个问题。当我参与一个在递归函数中调用DB的项目进行维护时,我的体验很糟糕...随着使用量的增加,recursvie函数的使用呈指数级增长,数据库调用达到了数千......

反正:

    function __GetChildrenRec($Lista, $Categoria){
        // Return false if $initialParent doesn't exist
        if ($Categoria == 0) $Categoria = "";
        if (!isset($Lista[$Categoria])) return FALSE;

        // Loop data and assign children by reference
        foreach ($Lista as $CategAtual) {
            if ($CategAtual[Parent] == $Categoria) {
                $Filhos[] = $CategAtual[ID];
                $Filhos = array_merge((array)$Filhos,(array)self::__GetChildrenRec($Lista, $CategAtual[ID]));
            }
        }

        // Return the data
        return is_array($Filhos) ? $Filhos : array();
    }

答案 1 :(得分:1)

除非它导致您出现真正的性能问题,否则没有理由避免递归。递归是大多数处理此类问题的开发人员可能尝试解决这些问题的方法,并且使用替代方法可能会损害可维护性,因为您的代码正在做一些需要在以后维护代码的人不会期望的事情。

一般来说,展开递归意味着管理堆栈。递归是一种获取您正在使用的语言来管理堆栈的方法,如果您不使用递归,那么您需要在函数内部自己操作堆栈。最简单的方法是使用array_push和array_pop,PHP中内置的函数允许您将数组用作堆栈。

与简单地使用递归相比,基于堆栈的方法相当复杂,如果递归给你带来问题,那么手动维护堆栈肯定会。确实存在一些好处,但老实说,我建议您尝试找出递归,因为它确实更容易处理,虽然它不像自己管理堆栈那样高效,但可能性能损失很大不会成为代码的瓶颈,因为PHP脚本中的瓶颈往往是PHP与外界(数据库,文件,网络连接等)的接口。

答案 2 :(得分:0)

使用第一种数组格式:

function list_children ($array, $initialParent) {

  // Return false if $initialParent doesn't exist
  if (!isset($array[$initialParent])) return FALSE;

  // Loop data and assign children by reference
  foreach ($array as &$item) {
    if (isset($array[$item['parent']])) {
      if (!isset($array[$item['parent']]['children'])) $array[$item['parent']]['children'] = array();
      $array[$item['parent']]['children'][] = &$item;
    }
  }

  // Return the data
  return (isset($array[$initialParent]['children'])) ? $array[$initialParent]['children'] : array();

}

这样做基本上是从第一个开始创建第二个数组,但它是通过引用来实现的 - 所以初始父代仍然可以通过它的ID找到并返回。返回子项数组,如果没有子项则返回空array();如果FALSE不存在则返回$initialParent