2010-07-18 7 views
2

J'ai un objet récursif, une liste chaînée vraiment:Comment convertir un objet récursif en Collection en C#?

public class LinkedList 
{ 
    public string UniqueKey { get; set; } 
    public LinkedList LinkedList { get; set; } 
} 

LinkedList aura un graphe d'objet qui finira par se terminer par LinkedList.LinkedList == null.

Je voudrais prendre tous les objets dans le graphique et les mettre dans une collection LinkedList afin que je puisse itérer sur eux. Comment est-ce que je fais cela en C#? Je me sens comme si il y a une façon très simple de faire cela en utilisant le rendement ou Linq vaudou?

Répondre

2

Quelque chose comme ça devrait fonctionner. Si vous avez le contrôle sur la classe, vous pouvez le faire directement à IEnumerable.

public class LinkedListEnumerable : IEnumerable<string> 
{ 
    LinkedList list; 
    public LinkedListEnumerable(LinkedList l) 
    { 
     this.list = l; 
    } 

    public IEnumerator<string> GetEnumerator() 
    { 
     LinkedList l = list; 
     while(l != null) 
     { 
      yield return l.UniqueKey; 
      l = l.Next; 
     } 
    } 
} 

Ensuite, vous pouvez parcourir plus de LinkedListEnumerable avec une boucle for-each.

+0

Oui, cela est juste. Sauf si vous prenez la question verbatim alors il devrait être «rendement rendement l» au lieu de «rendement retour l.UniqueKey» droit? Tout de même, il devrait être assez facile pour l'OP de comprendre cette partie. –

0

Est-ce ce que vous cherchez?

public class LinkedList 
{ 
    public string UniqueKey { get; set; } 
    public LinkedList LinkedList { get; set; } 

    public IEnumerable<LinkedList> GetAllNodes() 
    { 
     if (LinkedList != null) 
     { 
      yield return LinkedList; 
      foreach (var node in LinkedList.GetAllNodes()) 
       yield return node; 
     } 
    } 
} 
+2

Ce n'est pas très efficace. Pour une liste de 100 éléments, vous allez créer 100 énumérateurs, et le dernier élément doit les traverser avant de les renvoyer à l'appelant. – Guffa

0

Il n'y a pas de méthodes de LINQ belles dans la bibliothèque .NET standard pour permettre une élégante voodoo LINQ, mais vous pouvez utiliser Generate méthode de MoreLINQ projet et écrire ceci:

Enumerable 
    .Generate(list, l => l.LinkedList) 
    .TakeWhile(l => l != null).Select(l => l.UniqueKey); 

Il utilise Generate à créer une liste "infinie" de tous les éléments - elle n'est pas réellement infinie, car elle est générée paresseusement et nous arrêtons de l'utiliser dès que nous trouvons la valeur null à la fin (en utilisant TakeWhile). Ensuite, nous utilisons Select pour renvoyer une séquence de valeurs (au lieu de nœuds de liste liés).

Il s'agit essentiellement d'un bon moyen déclaratif d'exprimer la solution de boucle while affichée par Matthew (et il devrait avoir des performances à peu près similaires).

EDIT La méthode Generate ressemble à ceci:

IEnumerable<T> Generate(T current, Func<T, T> generator) { 
    while(true) { 
    yield return current; 
    current = generator(current); 
    } 
} 
+0

C'est génial, mais malheureusement je ne peux pas ajouter d'autres bibliothèques au projet. Je vais utiliser ceci sur de futurs produits cependant! –

+0

@Geoffrey: Vous pouvez ajouter la méthode 'Generate' à votre projet (il ne s'agit que de 3 lignes de code). –

Questions connexes