这是你所追求的?
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