這是你所追求的?
IEnumerable<record> ParentGetSomeRecords()
{
foreach(var item in someItems)
foreach(var record in GetSomeRecords())
yield return record;
}
如上所述,這隻會工作,爲孩子們的一個水平,但也是最相當於你的示例代碼。
更新
有些人似乎認爲要扁平化的層次結構的能力。這裏是執行廣度優先平坦化(讓孩子之前的兄弟姐妹)擴展方法:
從單個項目編輯:
[Pure]
public static IEnumerable<T> BreadthFirstFlatten<T>(this T source, Func<T, IEnumerable<T>> selector)
{
Contract.Requires(!ReferenceEquals(source, null));
Contract.Requires(selector != null);
Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);
var pendingChildren = new List<T> {source};
while (pendingChildren.Any())
{
var localPending = pendingChildren.ToList();
pendingChildren.Clear();
foreach (var child in localPending)
{
yield return child;
var results = selector(child);
if (results != null)
pendingChildren.AddRange(results);
}
}
}
這可以用於像這樣:
record rec = ...;
IEnumerable<record> flattened = rec.BreadthFirstFlatten(r => r.ChildRecords);
這將導致包含rec
的IEnumerable<record>
,所有recs兒童,所有兒童兒童等等等。
如果你是從records
集合的到來,使用下面的代碼:
[Pure]
private static IEnumerable<T> BreadthFirstFlatten<T, TResult>(IEnumerable<T> source, Func<T, TResult> selector, Action<ICollection<T>, TResult> addMethod)
{
Contract.Requires(source != null);
Contract.Requires(selector != null);
Contract.Requires(addMethod != null);
Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);
var pendingChildren = new List<T>(source);
while (pendingChildren.Any())
{
var localPending = pendingChildren.ToList();
pendingChildren.Clear();
foreach (var child in localPending)
{
yield return child;
var results = selector(child);
if (!ReferenceEquals(results, null))
addMethod(pendingChildren, results);
}
}
}
[Pure]
public static IEnumerable<T> BreadthFirstFlatten<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
Contract.Requires(source != null);
Contract.Requires(selector != null);
Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);
return BreadthFirstFlatten(source, selector, (collection, arg2) => collection.AddRange(arg2));
}
[Pure]
public static IEnumerable<T> BreadthFirstFlatten<T>(this IEnumerable<T> source, Func<T, T> selector)
{
Contract.Requires(source != null);
Contract.Requires(selector != null);
Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);
return BreadthFirstFlatten(source, selector, (collection, arg2) => collection.Add(arg2));
}
這兩個擴展方法可以用於像這樣:
IEnumerable<records> records = ...;
IEnumerable<record> flattened = records.BreadthFirstFlatten(r => r.ChildRecords);
還是從相反的方向:
IEnumerable<record> records = ...;
IEnumerable<record> flattened = records.BreadthFirstFlatten(r => r.ParentRecords);
所有這些擴展方法都是迭代的,所以不受堆棧大小的限制。
我有這些類型的方法,包括預購和後級深度優先遍歷整個主機的,如果你想看到他們,我會做一個回購,並將其上傳的地方:)
我在這種情況下,我不確定「一個平面的IEnumerable」是什麼意思 - 你能展示一個預期的返回類型/數據的例子嗎? – 2013-02-28 21:55:09
你**有**使用'yield return'嗎? – mattytommo 2013-02-28 21:55:37
如果您只想將數據作爲物化列表返回(不進行任何數據轉換),則可以使用GetSomeRecords()。ToList()。那是你要的嗎? – 2013-02-28 21:56:07