2012-01-18 111 views
1

我有一个包含嵌套对象等的对象。嵌套的级别可以假定为无限的。递归嵌套对象

如果对象嵌套其他对象,则应将子元素存储在名为childElements的数组属性中。

我与工作看起来像这样的对象:

Object 
    childElements 
     ['object1'] => object 
         childElements 
          ['object11'] => object 

     ['object2'] => object 

我想获得该对象的引用使用递归称为object11。这是我正在使用的功能。该功能属于一类,因此调用递归时$this使用:

public function recursiveSearch(array $childElements, $elementName){ 
    foreach ($childElements as $key => $element) { 
     var_dump($key); 
     if (isset($element->childElements)){ 

      return $this->recursiveSearch($element->childElements, $elementName); 

     }else{ 
      if ($key == $elementName){ 
       return $childElements[$elementName]; 
      } 
     } 
    } 

    throw new Exception("$elementName could not be found."); 
} 

然后我打电话给我的函数像这样(假设对象被称为$r):

return $this->recursiveSearch($r->childElements, 'object11'); 

的问题,我代码(当查看var dumps时,函数将继续向最内层对象行进,但一旦完成,它将终止,而不管它是否访问过任何其他childElements。我认为问题是由于return $this->recursiveSearch过早返回

如何构建我的递归函数以使其正常工作?

回答

1

问题是,你的代码假定如果一个元素有子元素,该元素必须在子元素中。实际上,你需要尽管三个条件:

  • 如果元素本身是被搜索到的元素,返回它
  • 如果元素孩子和被搜索到的元素是那些孩子,返回它
  • 如果没有上述所有元素,回归false(不抛出一个异常,因为没有找到该元素是可以预料的大多数儿童)

代码:

public function recursiveSearch(array $childElements, $elementName){ 
    foreach ($childElements as $key => $element) { 
     if ($key == $elementName) { 
      return $element; 
     } 
     if (
      !empty($element->childElements) && 
      $element = $this->recursiveSearch($element->childElements, $elementName) 
     ) { 
      return $element; 
     } 
    } 
    return false; 
} 
+0

工作完美:) – F21 2012-01-18 02:05:25

3

我相信你的逻辑问题在你的if-else语句中。您首先检查是否存在$ childElements,如果存在,则运行recursiveSearch。您需要首先测试关键匹配,然后检查孩子。这样,如果你找到它,你不会开始另一个递归。

tldr;如果(key == name){return element} else {recursionSearch}。

+0

+1为解释逻辑:) – F21 2012-01-18 02:06:24