2017-05-18 129 views
0

我需要遍歷以下類型的結構:用PHP遞歸函數版本

  P 
     / | \ 
    E1  E2  E3 ..... 
/\ /\ | 
    V1 V2 V1 V2 V3 ..... 
    | | | | /\ 
    T1 T2 T3 T4 T5 T6 ..... 

爲了形成包含下列元素的關聯數組:這裏

 V1(key) = [T1(E1), T3(E2), ...] 
     V2(key) = [T2(E1), T4(E2), ...] 
     V3(key) = [T5(E3), T6(E3), ...] 
     ..... 

現在到了棘手部:結構實際上被簡化了。我事先不知道需要處理多少個E級節點(圖中的3個),或者每個節點有多少個V級節點(但至少有1個節點在那裏),此外,每個V級節點也可以具有多個T節點。

我嘗試使用遞歸函數來做到這一點(在PHP中)。我會簡化代碼,因爲它對於一些對討論無關緊要的對象有奇怪的方法。我目前的嘗試結果如下:

 V1(key) = [T1(E1)] 
     V2(key) = [T2(E1)] 

我認爲這意味着遍歷只發生在第一個E級「分支」上。

這是我的代碼:

$result = []; 

$traverser = function($node) use (&$traverser, &$result) { 
    $children = $node->getChildrenArray(); 

    foreach($children as $key=>$child){ 
    if ($child->nodeType() == 'v_node') { 
     $v_node_key = $child->name; 

     $t_nodes = $child->getChildrenArray(); 

     if (!array_key_exists($v_node_key, $results)){ 
      $results[$v_node_key] = []; 
     } 

     foreach($t_nodes as $keyt=>$t_node) { 
      $info_array = $t_node->toArray(); 
      array_push($results[$v_node_key], $info_array); 
     } 

    } else if ($child->nodeType() == 'e_node') { 
     // keep digging 
     return $traverser($child); 
    } 

    } 
}; 

$traverser($p_node); 

我認爲問題是,一旦我稱之爲foreach$traverser功能也不會回來,從以前的狀態恢復。

任何人都可以建議我應該如何解決這個問題以得到我放在上面的結果嗎?

回答

1

好了,這是一個有點尷尬,我還不能完全肯定,如果這是正確的動機,但我通過rem解決了這個問題在我的代碼中輸入return

我認爲回報,讓我退出嵌套函數調用,而是我認爲它跳出了第一函數調用(在$traverser($p_node);線)。

即便如此,通過將return $traverser($child);行更改爲$traverser($child);它完成了它必須要做的事情。

希望這有助於任何人!

0

我沒有表現出對你有什麼錯誤,但我建議你改變你的功能成爲這個

function traverser($results, $node) { 
$children = $node->getChildrenArray(); 

foreach($children as $key=>$child){ 
    if ($child->nodeType() == 'v_node') { 
     $v_node_key = $child->name; 

     $t_nodes = $child->getChildrenArray(); 

     if (!array_key_exists($v_node_key, $results)){ 
      $results[$v_node_key] = []; 
     } 

     foreach($t_nodes as $keyt=>$t_node) { 
      $info_array = $t_node->toArray(); 
      array_push($results[$v_node_key], $info_array); 
     } 

    } else if ($child->nodeType() == 'e_node') { 
     // keep digging 
     return traverser($child); 
    } 

    } 
    return $results; 
} 

希望這有助於

+1

這有助於解決問題嗎?我希望你知道他的代碼**是一個有效的匿名函數**,並且他實際上正在與算法而不是語法進行鬥爭? –

0

好吧,既然你知道你有P-> E-> V-> T-節點,你可以簡單地去多的foreach循環,這樣

foreach($p_node->getChildren() as $e_node) { 
    $e_node_key = $e_node->name; 
foreach($e_node->getChildren() as $v_node) { 
    $v_node_key = $v_node->name; 
    foreach($v_node->getChildren() as $t_node) { 
    $t_node_key = $t_node->name; 
    // do whatever it needs to array_push to results 
    } 
} 
} 
+0

這是一種可能的方法,即使有點暴躁。 :)恐怕這不是一個解決方案,因爲我沒有真正講過我的問題的整個故事。我並不真正瞭解樹的深度,而不是它的寬度,所以遞歸匿名函數真的是一種方法。但是,謝謝你的想法。 – Joum

+0

我上面的評論意思是有時候我會在我的描述中開始遍歷P級別以上的級別,其他的我可能會從E級別開始,所以我試圖用一半的時間殺死所有的鳥類石。但它的作品! :D – Joum

+1

噢,那麼......你說得對。這不是一個解決方案;-) –