2012-12-19 24 views
2

我正在尋找訪問和編輯以下樹結構,並找不到在interwebs上的好方法。動態自定義樹訪問

class SimpleNode 
{ 
    string Name; 
    SimpleType Type; 
    List<SimpleList> Children; 
} 

class SimpleList 
{ 
    //some list-based properties 
    List<SimpleNode> Items; 
} 

我需要能夠查找和編輯節點,而不訴諸:

Node.Children[0].Items[0].Children[1].Items[3] 

等。我試圖通過返回樹元素的函數來實現,但編輯返回的元素似乎並沒有影響實際的樹。增加複雜性的是,我不想排除兩個相同的節點存在於樹中的不同點。

很明顯,這是我第一次用樹結構,真的可以使用一些幫助。


經過進一步調查(根據德魯),複合模式的概念是有道理的,特別是方法轉發/聚合返回的概念。這裏的訣竅是我可能有兩個節點具有相同的標識符(類型&名稱)在樹中的兩個不同點。

,沒有工作的代碼是類似的東西(它早已不復存在):

Node GetNode(Type type, string name) 
{ // returns node } 

我想是這樣的:

Node nodeToEdit = GetNode(params); 
nodeToEdit.Name = "New Name"; 

nodeToEdit.Children.Add(new Node()); 

但它沒似乎沒有在樹上。如果它應該有,讓我知道,因爲我一定錯過了什麼。

+2

是元素類還是結構? – SWeko

+0

你能詳細說明'edit'是什麼意思嗎?你究竟需要做什麼? –

+0

這被稱爲[Composite Pattern](http://en.wikipedia.org/wiki/Composite_pattern)。我建議你閱讀它然後擴展你的問題。 –

回答

0

正如評論中所述,在使用樹木時,您遲早會在樹上行走並對物品執行操作。通常,您使用某種類型的遞歸函數來接收一個節點作爲參數,並且與孩子一起調用自己。

在您的示例中,樹中有兩種不共享通用接口的項目。這增加了一些複雜性,因爲您必須檢查兩種類型的項目。

下面的示例顯示了一個簡單的走樹的功能。該方法接收節點作爲參數和節點的級別。此外,還有兩個回調:一個用於SimpleNode項目,另一個用於SimpleList項目。由於走樹的過程相同,因此可以共享此代碼並提供處理場景樹的元素的特定方法。

void TreeWalk(SimpleNode node, int level, Action<SimpleNode, int> inspectNode, Action<SimpleList, int> inspectList) 
{ 
    if (node == null) 
     return; 
    if (inspectNode != null) 
     inspectNode(node, level); 
    foreach(var simpleLst in node.Children) 
    { 
     if (inspectList != null) 
      inspectList(simpleLst, level + 1); 
     foreach(var child in simpleLst.Items) 
      TreeWalk(child, level + 2, inspectNode, inspectList); 
    } 
} 

由於需要節點,所以方法首先驗證輸入參數。然後它調用可以在SimpleNode上執行操作的回調方法。如果滿足某些標準,則此類操作的示例可能是更改節點值。

該方法然後檢查節點的孩子。首先,它調用SimpleList項目的回調方法,然後迭代simpleListItems。對於每個節點,它都會爲孩子再次調用自己。級別也遞增。

以下示例顯示如何在滿足某些條件的情況下更改節點值。由於SimpleList項目不需要執行任何操作,因此將null用作相應回調的參數。

// Change node "11" to "11x" 
var nameToLookFor = "11"; 
var newName = "11x"; 
TreeWalk(data, 0, 
    (node, level) => { 
     if (node.Name == nameToLookFor) 
      node.Name = newName; 
    }, 
    null); 

由於測試的原因,打印樹的內容很有幫助。您可以使用另一組回調方法實現此目的:

TreeWalk(root, 0, 
    (node, level) => Console.WriteLine(new String(' ', level * 2) + string.Format("Node: {0} - {1}", node.Name, node.Type)), 
    (list, level) => Console.WriteLine(new String(' ', level * 2) + "List"));