Cập nhật:
Đối với những người quan tâm đến mức độ làm tổ (độ sâu). Một trong những điều tốt về việc triển khai ngăn xếp liệt kê rõ ràng là tại bất kỳ thời điểm nào (và đặc biệt là khi cung cấp phần tử), nó stack.Count
thể hiện độ sâu xử lý hiện tại. Vì vậy, có tính đến điều này và sử dụng các bộ giá trị C # 7.0, chúng ta có thể chỉ cần thay đổi khai báo phương thức như sau:
public static IEnumerable<(T Item, int Level)> ExpandWithLevel<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
và yield
tuyên bố:
yield return (item, stack.Count);
Sau đó, chúng tôi có thể thực hiện phương pháp ban đầu bằng cách áp dụng đơn giản Select
ở trên:
public static IEnumerable<T> Expand<T>(
this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector) =>
source.ExpandWithLevel(elementSelector).Select(e => e.Item);
Nguyên:
Đáng ngạc nhiên là không ai (ngay cả Eric) cho thấy cổng lặp lại "tự nhiên" của một DFT đặt trước đệ quy, vì vậy đây là:
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();
}
}