2017-02-27 98 views
1

我有一個多維數組的對象(請參閱下面的示例數據)。現在我想在數據中搜索一個值(或屬性)。如果找到該值,該函數應返回正確的對象並停止搜索。PHP:使用遞歸函數從多數組中搜索並返回值

我發現了三個解決方案來做到這一點遞歸函數。但沒有像上面描述的那樣工作。

首先是我自己的解決方案:

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL) 
{ 
    foreach($folderContentDetails as $key => $item) 
    { 
     if($item->url === $url) 
     { 
      $result = $item; 
     } 
     elseif($item->elementType === "folder") 
     { 
      $result = self::getPathForUrl($item->folderContent, $url, $result); 
     } 
    } 
    return $result; 
} 

如果你這樣調用該函數:

print_r(self::getPathForUrl($data, 'order/abc/alpha'); 

然後返回正確的對象。缺點是,該函數搜索整個數據並最終返回結果。我找不到停止函數的方法,如果找到了結果,那麼它浪費資源。

第二(標準 - )解決方案,你將在網絡上找到的,看起來是這樣的:

public static function getPathForUrl($folderContentDetails, string $url) 
{ 
    foreach($folderContentDetails as $key => $item)  
    { 
     if($url === $item->url OR ($item->elementType == "folder" && Folder::getPathForUrl($item->folderContent, $url) !== false)) 
     { 
      print_r('inner: <br/>'.$item->url); 
      // prints more then one value, depending on your data, in my case : 
      // /order/abc/alpha 
      // /order/abc 
      // /order 
      return $item; 
     } 
    } 
    return false; 
} 

,此功能將停止,如果找到正確的價值。但由於某種原因它返回多個對象,並且最終的對象是錯誤的(參見代碼註釋)。

最後的解決方案是這樣的:

public static function getPathForUrl($folderContentDetails, string $url) 
{   
    foreach($folderContentDetails as $key => $item) 
    { 
     if($item->elementType == "folder" && $item->url != $url) 
     { 
      return self::getPathForUrl($item->folderContent, $url); 
      // iterates only the first sub-folder, then stops 
     } 
     elseif($item->url == $url) 
     { 
      print_r($item); //nothing, if not found in first sub-folder 
      return $item; // nothing, if not found in first sub-folder 
     } 
    } 
    return false; 
} 

如果返回遞歸函數的結果,則函數下降到第一嵌套元素和停在那裏,所以它不會再次上升到搜索其他元素。

如果不返回結果,函數將搜索整個數據,但當然不返回正確的對象。

我可能不明白正確的遞歸概念。任何幫助都非常受歡迎。

這些都是一些示例數據:

Array 
(
[0] => stdClass Object 
    (
     [elementType] => folder 
     [path] => 
     [url] => /getting-started 
     [folderContent] => Array 
      (
       [0] => stdClass Object 
        (
         [elementType] => file 
         [path] => \0_getting_started\01-installation.md 
         [url] => /getting-started/installation 
        ) 

       [1] => stdClass Object 
        (
         [elementType] => file 
         [path] => \0_getting_started\02-system-settings.md 
         [url] => /getting-started/system-settings 
        ) 

       [2] => stdClass Object 
        (
         [elementType] => file 
         [path] => \0_getting_started\index.md 
         [url] => /getting-started/index 
        ) 

      ) 

    ) 

[1] => stdClass Object 
    (
     [elementType] => folder 
     [path] => 
     [url] => /order 
     [folderContent] => Array 
      (
       [0] => stdClass Object 
        (
         [elementType] => folder 
         [path] => \2_order 
         [url] => /order/abc 
         [folderContent] => Array 
          (
           [0] => stdClass Object 
            (
             [elementType] => file 
             [path] => \2_order\abc\alpha.md 
             [url] => /order/abc/alpha 
            ) 
          ) 

        ) 
      ) 

    ) 

[3] => stdClass Object 
    (
     [elementType] => file 
     [path] => \index.md 
     [url] => /index 
    ) 
) 

回答

0

返回退出函數,所以如果你想第一個結果只返回它在你的病情

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL) 
{ 
    foreach($folderContentDetails as $key => $item) 
    { 
     if($item->url === $url) 
     { 
      return $item; 
     } 
     elseif($item->elementType === "folder") 
     { 
      $result = self::getPathForUrl($item->folderContent, $url, $result); 
     } 
    } 
    return $result; 
} 
+1

那麼簡單,當然;)我只是忽視了木材的樹木,黑客逛了一天後,謝謝! – user2429958

0

如果你想匹配後停止價值是成立的;只是在條件內返回;

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL) 
{ 
    foreach($folderContentDetails as $key => $item) 
    { 
     if($url === $item->url) 
     { 
      return $item; 
     } 

     if("folder" === $item->elementType) 
     { 
      return self::getPathForUrl($item->folderContent, $url, $result); 
     } 
    } 
} 

PS:在牢記的最佳做法,如果/返回:)