Mettre à jour:
Pour les personnes intéressées par le niveau de nidification (profondeur). L'un des avantages de l'implémentation explicite de la pile d'énumérateurs est qu'à tout moment (et en particulier lors de la production de l'élément), le stack.Count
représente la profondeur de traitement en cours. Donc, en prenant cela en compte et en utilisant les tuples de valeur C # 7.0, nous pouvons simplement modifier la déclaration de méthode comme suit:
public static IEnumerable<(T Item, int Level)> ExpandWithLevel<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
et yield
déclaration:
yield return (item, stack.Count);
Ensuite, nous pouvons implémenter la méthode originale en appliquant simple Select
sur ce qui précède:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector) =>
source.ExpandWithLevel(elementSelector).Select(e => e.Item);
Original:
Étonnamment, personne (même Eric) n'a montré le port itératif "naturel" d'un DFT de pré-commande récursif, alors le voici:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}