2009-04-09 9 views

Répondre

2

Quelque chose comme ceci:

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; 
     } 
} 

Vous pouvez ensuite appeler cela contre le nœud racine comme une méthode d'extension:

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

Cela fonctionne pour moi. Je n'ai pas encore compris les méthodes d'extension, donc je ne sais pas si c'est performant. Mais c'est une solution élégante. De ce que je vois, seuls les descendants d'une entrée donnée sont vérifiés. J'ai dû modifier AllDescendants pour vérifier le type de noeud d'entrée et le céder. Merci –

+0

En fait, je devais créer un nœud racine spécial, puis passer cela. Modifier AllDescendants était faux. Merci –

+0

Les méthodes d'extension sont converties au moment de la compilation en appels statiques normaux - il n'y a aucune implication de performance pour les utiliser. Cette méthode gère la récursivité, donc j'en aurais potentiellement une similaire qui a fonctionné sur les nœuds de la racine de l'arbre, puis appelée cela. – Keith

1

En supposant que votre arbre est générique. c'est-à-dire Item<T>.

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

Sinon, analyser chaque noeud et comparer « item == typeof(T) »

2

Eh bien, en interne la méthode aurait pour itérer sur tous les éléments de l'arbre, de sorte que le saut juste énumérer dessus, et en utilisant le OfType méthode LINQ est pas loin:

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

+1 pour avoir donné la bonne réponse :) Je viens de réaliser que j'ai raté le point –

1

Qu'est-ce que vous avez besoin est une fonction traversal arbre de base (pré-commande, afinde ou postorder - ce n'a pas d'importance) et une fonction de filtre. Ensuite, vous pouvez composer ces deux ensemble et obtenir ce dont vous avez besoin:

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

Idée similaire à la mienne, mais je ferais un changement: vous faites la conversion deux fois - 't comme U' et la vérification de null est plus rapide classes que si (t est U) (U) t'; – Keith

Questions connexes