Ðаn*_*Ðаn 1 c# linq iterator yield-return
我很难找到用于以下迭代器块的正确LINQ语法:
class Program
{
class Operation
{
public IEnumerable<Operation> NextOperations { get; private set; }
}
class Item { }
static Item GetItem(Operation operation)
{
return new Item();
}
static IEnumerable<Item> GetItems(IEnumerable<Operation> operations)
{
foreach (var operation in operations)
{
yield return GetItem(operation);
foreach (var item in GetItems(operation.NextOperations)) // recursive
yield return item;
}
}
static void Main(string[] args)
{
var operations = new List<Operation>();
foreach (var item in GetItems(operations))
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
也许我所拥有的一切都是如此美好?对于这个特定的代码,yield return在一个显式内部foreach确实是正确的解决方案?
也许我所拥有的一切都是如此美好?
这是相当不错.我们可以让它稍好一点.
对于这个特定的代码,显式foreach中的yield return确实是正确的解决方案吗?
这是一个合理的解决方案.它易于阅读并且清晰正确.正如我前面提到的那样,如果树非常深,那么性能可能就不好了.
这是我将如何做到这一点:
static IEnumerable<T> AllNodes(this T root, Func<T, IEnumerable<T>> getChildren)
{
var stack = new Stack<T>();
stack.Push(root);
while(stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach(var child in getChildren(current).Reverse())
stack.Push(child);
}
}
static void Main()
{
var operation = whatever;
var items = from op in operation.AllNodes(x=>x.NextOperations)
select GetItem(op);
foreach (var item in items)
{
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,只有在您关心迭代"按顺序"时才需要调用Reverse().例如,假设操作Alpha具有子操作Beta,Gamma和Delta,而Delta具有子Zeta和Omega.遍历如下:
push Alpha
pop Alpha
yield Alpha
push Delta
push Gamma
push Beta
pop Beta
yield Beta
pop Gamma
yield Gamma
pop Delta
yield Delta
push Omega
push Zeta
pop Zeta
yield Zeta
pop Omega
yield Omega
Run Code Online (Sandbox Code Playgroud)
现在堆栈是空的所以我们已经完成了,我们以"preorder traversal"顺序获取项目.如果你不关心订单,如果你需要的只是确保你得到所有这些,那么就不要费心去反转孩子了,你会按照Alpha,Delta,Omega,Zeta的顺序得到它们. ,Gamma,Beta.
合理?