Memperbarui:
Untuk orang yang tertarik dengan level nesting (kedalaman). Salah satu hal baik tentang implementasi tumpukan enumerator eksplisit adalah bahwa setiap saat (dan khususnya saat menghasilkan elemen) stack.Count
mewakili kedalaman pemrosesan saat ini. Jadi dengan mempertimbangkan hal ini dan memanfaatkan tupel nilai C # 7.0, kita cukup mengubah deklarasi metode sebagai berikut:
public static IEnumerable<(T Item, int Level)> ExpandWithLevel<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
dan yield
pernyataan:
yield return (item, stack.Count);
Kemudian kita dapat mengimplementasikan metode asli dengan menerapkan simple Select
di atas:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector) =>
source.ExpandWithLevel(elementSelector).Select(e => e.Item);
Asli:
Anehnya tidak ada (bahkan Eric) yang menunjukkan port berulang "alami" dari DFT pra-order rekursif, jadi ini dia:
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();
}
}