2009-12-02 229 views
1

我有一個儲存像這樣的數組:找到多維數組中的路徑一定ID

[0] => Array 
    (
     [id] => 1 
     [cat_name] => c1 
    ) 

[1] => Array 
    (
     [id] => 2 
     [cat_name] => c2 
     [copii] => Array 
      (
       [0] => Array 
        (
         [id] => 5 
         [cat_name] => c21 
        ) 

       [1] => Array 
        (
         [id] => 6 
         [cat_name] => c22 
        ) 

      ) 

    ) 

[2] => Array 
    (
     [id] => 3 
     [cat_name] => c3 
     [copii] => Array 
      (
       [0] => Array 
        (
         [id] => 7 
         [cat_name] => c31 
         [copii] => Array 
          (
           [0] => Array 
            (
             [id] => 9 
             [cat_name] => c311 
            ) 

          ) 

        ) 

       [1] => Array 
        (
         [id] => 8 
         [cat_name] => c32 
        ) 

      ) 

    ) 

我試圖找到找到一個途徑,以一定的ID更簡單的方法。 現在我使用foreach遍歷所有可能的數組並找到路由。

例子:

id = 1: 
    route[0][id]=1,route[0][cat_name]=c1 
id = 5: 
    route[0][id]=2,route[0][cat_name]=c2 
    route[1][id]=5,route[1][cat_name]=c21 
id = 9: 
    route[0][id]=3,route[0][cat_name]=c3 
    route[1][id]=7,route[1][cat_name]=c31 
    route[2][id]=9,route[2][cat_name]=c311 

如果我的問題是沒有意義的,我責備它花了試圖找到一個很好的解決方案,它的時間...

回答

1

代替發佈一堆代碼,我建議你閱讀遞歸,如果你不知道它。 PHP在遞歸方面並不是太好,但它確實是你唯一的選擇。

基本上你會調用一個函數,該函數需要數組,id來查找,以及表示路徑的字符串/數組。最初使用空字符串或空數組調用後者參數。

在你會做這樣的功能:

  • 貫穿的$array
  • 頂層一個foreach如果您發現$id你正在尋找,返回$path
  • 如果其中一個數組值是一個子數組,則添加當前的ID節點並再次調用該函數 - 例如$foundPath = findPath($array, $id, $path)
  • 如果$foundPath返回一些東西,那麼您已經獲得了路徑並可以返回。
  • 如果它沒有找到任何東西($foundPath爲false或null,如下所示),則保留它並繼續循環的下一次迭代。
  • 在循環結束時,如果您沒有找到任何內容,則返回false或null。

希望有幫助!

+0

我試圖避免遞歸算法,我知道他們,使用它們,但我試圖得到迭代解決方案...如果我不能,然後我卡住了一個遞歸的,但它不是我的第一個選項 – Raz 2009-12-02 09:37:17

+0

如果你的數組深度未知,那麼就我所知,遞歸是唯一的解決方案。即使它的深度不超過3個數組,遞歸仍然是比幾個嵌套循環更乾淨的代碼。 – DisgruntledGoat 2009-12-02 09:47:06

+0

它的最大深度爲3,我現在正在測試遞歸和迭代解決方案的效率... 我會在今天晚些時候用解決方案更新問題 – Raz 2009-12-04 07:12:23

0

你的問題確實是沒有意義的。 「尋找路線」是什麼意思?

它看起來像你的數組有一個遞歸結構描述一個圖形;用於查找最短路徑的圖遍歷算法可能更合適(即將數組轉換爲圖數據結構 - 可能是一個節點列表+邊列表,並在其上運行圖算法)。

+0

是的,它的結構有點像圖,但我試圖避免改變結構 – Raz 2009-12-02 09:38:32

1

遞歸是你想要什麼:

<?php 

    function walk_array(array $a, &$ra, $path, $depth = 0) { 
    $id= isset($path[$depth]) ? $path[$depth] : null; 
    if (!is_null($id)) { 
     foreach ($a as $a2) { 
     if ($a2['id'] == $id) { 
     $ra[$depth]= $a2; 
     unset($ra[$depth]['copii']); 
     // This is the key bit - recursion is simply a function calling itself: 
     if (isset($a2['copii'])) 
     walk_array($a2['copii'], $ra, $path, ++$depth); 
     } 
     } 
    } 
    } 

    $complex_array= array(
     array('id'=> 1, 'name'=> 'Node #1', 'copii'=> array(
     array('id'=> 3, 'name'=> 'Node #3', 'copii'=> array(
     array('id'=> 4, 'name'=> 'Node #4') 
     )) 
    )), 
     array('id'=> 2, 'name'=> 'Node #2', 'copii'=> array(
     array('id'=> 5, 'name'=> 'Node #5', 'copii'=> array(
     array('id'=> 6, 'name'=> 'Node #6',) 
     )) 
    )), 
    );  

    // Prints out nodes 1,3,4 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(1, 3, 4)); 
    print_r($ra); 

    // Prints out nodes 2,5,6 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(2, 5, 6)); 
    print_r($ra); 

    // Prints out empty array 
    $ra= array(); 
    walk_array($complex_array, $ra, array(5, 2, 4)); 
    print_r($ra); 

    // Prints out nodes 2,5 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(2, 5)); 
    print_r($ra); 
?> 
+0

遞歸,但據我在php中看到這不是最好的解決方案,這就是爲什麼我試圖避免它 – Raz 2009-12-02 09:36:08

0

我能想到的另一種方式 - 避免遞歸 - 是用「變量變量」,所以你只是試圖數組索引的每一個可能的組合,由點。

$search = 3; 
$ind = '$arr[0][copii][1]'; // generated somehow 
if (isset(${$ind}['id']) && ${$ind}['id'] == $search) { 
    // we found it 
} 

這將花費同樣長的時間,您不能保證找到任何東西。也正如我寫這篇文章,我正在努力想辦法去產生$ind值...除了遞歸。我想你可以生成3位數的數字,如000,001,002,並使用每個字符來創建索引,如$arr[0][copii][0][copii][0],$arr[0][copii][0][copii][1]$arr[0][copii][0][copii][2]

此方法仍然不完美,因爲您無疑會錯過值並查找大量不存在的值。說實話,遞歸是代碼明智的更簡單更清潔的選擇,除非你的數組有數百個條目,那麼你不會注意到一個很大的性能問題。

相關問題