【问题标题】:PHP Recursive Function to get n generations of x parentsPHP递归函数获取n代x父母
【发布时间】:2015-02-28 01:03:41
【问题描述】:

我需要从一个人(作为 $id 参数传递)开始返回“x”代(作为 $generations 参数传递)的家庭数据(父母、兄弟姐妹和伴侣)。我不能假设有两个父母,这个特定的家谱模型必须允许动态数量的父母(允许生物和收养关系)。我认为我的递归是向后的,但我不知道如何。

下面的代码触发了我的基本子句 5 次,每一代一次,因为 $generation 不是针对每个 SET 父母而是针对每个父母减少 1。我想要的是只触发一次基本子句($generations == 0),当获取初始人的所有父母的“x”代时。

public function fetchRelationships($id = 1, $generations = 5, $relationships = array())
{
  $perId = $id;
  if ($generations == 0) {
            return $relationships;
        } else {
            $parents = $this->fetchParents($perId);
            $relationships[$perId]['parents'] = $parents;
            $relationships[$perId]['partners'] = $this->fetchPartners($perId);
            if (!empty($parents)) {
                --$generations;
                foreach ($parents as $parentRel) {
                    $parent = $parentRel->getPer2();
                    $pid = $parent->getId();
                    $relationships[$perId]['siblings'][$pid] = $this->fetchSiblings($perId, $pid);
                    $perId = $pid;
                    $relationships[$perId] = $this->fetchRelationships($perId, $generations, $relationships);
                }
            }

            return $relationships;
        }
}

fetchPartners、fetchParents 和 fetchSiblings 方法只是获取匹配的实体。所以我不会在这里粘贴它们。假设有 2 个父代,5 代并且每一代有 2 个父代,那么返回数组应该包含 62 个元素,并且只有在这 62 个元素被填充后才应该触发基本子句。

提前感谢您的帮助。

-----------编辑--------

已重写 fetchSiblings 和 fetchPartners 代码,以使其更易于阅读:

public function fetchRelationships($id = 1, $generations = 5, $relationships = array())
{
  $perId = $id;
  if ($generations == 0) {
            return $relationships;
        } else {
            $parents = $this->fetchParents($perId);
            $relationships[$perId]['parents'] = $parents;
            if (!empty($parents)) {
                --$generations;
                foreach ($parents as $parentRel) {
                    $perId = $parentRel->getPer2()->getId();
                    $relationships[$perId] = $this->fetchRelationships($perId, $generations, $relationships);
                }
            }

            return $relationships;
        }
}

【问题讨论】:

  • 这五次可能是巧合,并非基于世代数。它将不得不多次调用“base”子句,因为它不是一个基础,它是一个尾巴。当你上树时,家庭就会分支。当世代 = 0 时,您处于伟大、伟大、曾祖父母的位置。而且你有不止 1 个!
  • 是的,但我不知道如何解决它。我绝对不希望它在“整棵树完成”之外的任何条件下击中基本子句。我一直在关注广度,但我不确定它是否适用于此。
  • 它必须多次击中它。没关系。您遇到了更大的问题,因为您只创建了一个数组,然后该数组具有引用主数组的条目。
  • 感谢您的回复。我知道我编写代码的方式意味着它会不止一次地碰到子句,这就是我需要帮助的问题。传递数组以便它可以填充来自后代的数据,这不是我的主要问题。我不相信这是一个问题。如果我的递归是向后的,我认为是,那么我希望有人能够帮助我实现这一点。
  • 当您迭代父关系时,您会修改 $perId ... 这似乎很奇怪,因为在下一次迭代中,您似乎会查询父级的兄弟姐妹是它自己的父级 = S

标签: php recursion breadth-first-search


【解决方案1】:

Garr Godfrey 做对了。当到达每个分支的末尾时,$generations 将为零。因此,只要有分支,您就会多次点击“基本子句”。在foreach ($parents as $parentRel) 循环中,您为每个父级调用fetchRelationships。那是两个分支,因此您将对“基本子句”进行两次调用。然后对于他们的每个父母,您将再调用两次“基本子句”,依此类推...

此外,您正在来回传递relationships,使其元素指向自身。我意识到你只是想在你去的时候保留信息,但你实际上是在创建很多不必要的自我引用。

试试这个

public function fetchRelationships($id = 1, $generations = 5)
{
  $perId = $id;
  $relationships = array();
  if ($generations == 0) {
            return $relationships;
        } else {
            $parents = $this->fetchParents($perId);
            $relationships[$perId]['parents'] = $parents;
            if (!empty($parents)) {
                --$generations;
                foreach ($parents as $parentRel) {
                    $perId = $parentRel->getPer2()->getId();
                    $relationships[$perId] = $this->fetchRelationships($perId, $generations);
                }
            }

            return $relationships;
        }
}

您仍然会多次点击基本子句,但这不重要。

您可能会想“但我会丢失$relationships 中的一些数据”,但您不会。这一切都来自递归返回。

【讨论】:

    【解决方案2】:

    如果你要从数据库中提取这个,have you considered having the query do all of the leg work for you?

    不确定您需要如何堆叠或排除数据,但这是一种方法:

    <?php   
    
    class TreeMember {
        public $id;
        // All three should return something like:
        // array( $id1 => $obj1, $id2 => $obj2 )
        // and would be based on $this->$id
        public function fetchParents(){ return array(); }
        public function fetchPartners(){ return array(); };
        public function fetchSiblings(){ return array(); }; 
    
        public function fetchRelationships($generations = 5)
        {
            // If no more to go
            if ($generations == 0) { return; }   
    
            $branch = array();
            $branch['parents'] = $this->fetchParents();
            $branch['partners'] = $this->fetchPartners();
            $branch['partners'] = $this->fetchSiblings();   
    
            // Logic
            $generations--;
            foreach($branch as $tmType, $tmArr)
            {
                foreach($tmArr as $tmId => $tmObj)
                {
                    $branch[$tmType][$tmId] =
                        $mObj->fetchRelationships
                        (
                            $generations
                        )
                    );
            }); 
    
            return array($this->id => $branch);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 2011-05-02
      • 2021-08-04
      • 2016-01-28
      • 2021-06-29
      相关资源
      最近更新 更多