2009-04-09 4 views

答えて

2

このような何か:

foreach(MyCustomNodeClass item in rootNode.AllDescendantNodes<MyCustomNodeClass>()) 
{ 
    ... 
} 

internal static IEnumerable<T> AllDescendantNodes<T>(this TreeNode input) 
    where T class; 
{ 
    T current = null; 
    foreach (TreeNode node in input.Nodes) 
     if((current = node as T) != null) 
     { 
      yield return current; 
      foreach (var subnode in node.AllDescendantNodes<T>()) 
       yield return subnode; 
     } 
} 

あなたはその後、拡張メソッドとしてルートノードに対してこれを呼ぶだろう

+0

それは私のために働く。私はまだ拡張メソッドの理解がないので、それが実行可能かどうかについては不明です。しかしそれは優雅な解決策です。私が見るものからは、与えられた入力の子孫のみがチェックされています。私は、入力ノードタイプをチェックしてそれを得るためにAllDescendantsを修正しなければなりませんでした。ありがとう –

+0

実際に、私は特別なルートノードを作成し、それを渡す必要がありました。AllDescendantsを変更するのは間違っていました。ありがとう –

+0

拡張メソッドは、コンパイル時に通常の静的呼び出しに変換されます。このメソッドは再帰を処理するので、私は潜在的にツリーのルートノードで動作し、これを呼び出す同様のものを持つでしょう。 – Keith

1

あなたの木は一般的だと仮定します。すなわちItem<T>です。

int count = yourTree.Count(p => p == typeof(T)); 

そうでない場合は、各ノードを解析し、「item == typeof(T)

2

まあ、内部的方法は、ツリーのすべての要素を反復しなければならないので、スキップがちょうどその上に列挙し、使用することを比較OfType LINQメソッドはそこまでではありません。

var onlyTs = yourTree.OfType<SomeT>(); 
+0

正しい答えを与えるために+1 :)ちょうど私がポイントを見逃したことを理解しました –

1

あなたが必要なものの基本的なツリートラバーサル機能である(先行順、順序どおりまたは後順 - これは重要ではありません)とフィルタ機能。その後、一緒にそれらの2を構成し、必要なものを手に入れることができます。

IEnumerable<T> Traverse(Tree<T> tree) 
{ 
    yield return tree.Data; 

    foreach(Tree<T> subtree in tree.Subtrees) 
     foreach(T t in Traverse(subtree)) 
      yield return t; 
} 

IEnumerable<U> Filter<T, U>(IEnumerable<T> source)   
    where U : T 
{ 
    foreach(T t in source) 
     if(t is U) 
      yield return (U)t; 
} 
+0

私と同様のアイデアですが、私は1つの変更を行います:あなたは2回の変換を行っています - 't as U'を、クラスより'if(tはU)(U)t'; – Keith