J'ai une classe comme:
class Spline int ChildrenCount; Spline GetChild (int index) class SplineCollection : IEnumerable<Spline> Spline Master
7 Réponses :
Cela fera une première traversée de la technologie de profondeur de la boîte code> code> 'arbre'. Vous pouvez alors simplement appeler cette méthode sur la case code> code> pour renvoyer tous les enfants récursifs.
public class Box { // ... public IEnumerable<Box> GetBoxes() { yield return this; for (int i=0; i<box.ChildrenCount; i++) { foreach (Box child in box.GetChild(i).GetBoxes()) { yield return child; } } } }
Merci mais cela va-t-il passer par les enfants de chaque boîte.getchild (i) aussi?
Ah, maintenant ça a du sens. Édité la réponse.
class Box { int ChildrenCount; Box GetChild (int index){/* some implementation*/} public IEnumerable<Box> Children { get { for(int i = 0; i != ChildrenCount; ++i) yield return GetChild(i); } } public IEnumerable<Box> Descendants { get { foreach(Box child in Children) { yield return child; foreach(Box desc in child.Descendants) yield return desc; } } } } You can call this from BoxCollection, but since Box is already a collection of Boxes, I don't see what BoxCollection's purpose is here. For that matter, having Box implement IEnumerable<Box> or one of its descendants (ICollection<Box>, IList<Box>) would probably improve usefulness.It's also possible to do it in an iterative rather than recursive manner, which sometimes has a better performance (pretty much any time that the compiler doesn't turn the recursion into interation anyway), but recursive is more readable and normally more than performant enough.
Bien sûr. Vous n'avez même pas vraiment besoin de BoxContainer, puisque la boîte, par son nom, existe sous la forme d'un conteneur: si la boîte a des boîtes de béquille B et C, BOX B TENUE BOXES DR E, et boîte C tenue Box F, l'énumérable sortirait A, B, D, E, C, F. P> P>
Votre foreach code> entraîne effectivement un type de retour de
ienumerable
code> dans un rendement
! Code> et cela fonctionnerait bien.
Vous avez exactement raison. Éditer rapidement pour itérer à travers l'iEnumérable retourné par la boîte enfant.
Oui, mais vous devez énumérer le résultat récursif. Vous ne pouvez pas simplement donner le retour, car le type ne correspond pas.
IEnumerable<int> Triangle(int n) { yield return n; if (n > 0) foreach (var e in Triangle(n - 1)) yield return e; }
J'irais avec maintenir manuellement une pile au lieu de s'appuyer ici sur la pile d'appels ici. La raison en est qu'un nouveau iEnumerable
Spline code> visité si vous avez utilisé la pile d'appel en appelant récursivement la méthode qui obtient les descendants. Ce serait inefficace. Vous pouvez améliorer considérablement la traversée en utilisant votre propre pile.
public IEnumerable<Spline> Descendants
{
get
{
// This performs a simple iterative preorder traversal.
var stack = new Stack<Spline>(new Spline[] { this });
while (stack.Count > 0)
{
Spline current = stack.Pop();
yield return current;
for (int i = current.ChildrenCount - 1; i >= 0; i--)
{
stack.Push(current.GetChild(i));
}
}
}
}
J'aimerais pouvoir voter cela 10 fois. C'est donc i> beaucoup plus efficace qu'une solution récursive et ne nécessite que quelques secondes de plus de réflexion. En fait, vous pouvez généraliser cela dans une fonction code> aplatissée code> pour simplifier tout itérateur récursif.
Cela renvoie également également l'élément racinaire, pas seulement les descendants réels.
Cela ajoute à la grande réponse de Brian Gideon, qui fournit uniquement uniquement les descendants, sans l'élément racinaire. Il utilise en outre Voici mon code (): p> foreach code>, qui peut être disponible par exemple dans des contextes EF.
/// <summary>
/// Retrieves all descendants.
/// </summary>
public IEnumerable<Item> Descendants {
get {
// This performs a simple iterative preorder traversal.
Stack<Item> stack = new Stack<Item>(this.Children);
while (stack.Count > 0) {
Itemcurrent = stack.Pop();
yield return current;
//Push current's children
foreach (Item currentChild in current.Children) {
stack.Push(currentChild);
}
}
}
}
Je suppose que vous voulez dire "descendants" lorsque vous écrivez des "enfants", car les enfants ne nécessitent aucune récursion.
@Job, oui vous avez raison, je voulais dire des descendants. C'est juste que dans le SDK que j'utilise, ils sont toujours appelés enfants, enfantsRecursive, c'est pourquoi je viens d'utiliser cela.