树中嵌套产量的性能
我有一个树状结构。 该结构中的每个元素都应该能够返回它作为根的所有元素的 Enumerable。 我们将此方法称为 IEnumerable
A <-- topmost root
/ \
/ \
B C
/ \ / \
D E F G
元素 C
调用 GetAll
返回 {C, F, G}
(元素的固定顺序会很好,但是不需要)。 我想每个人都已经知道了。
GetAll
的当前实现如下所示:
public IEnumerable<Foo> GetAll ()
{
yield return this;
foreach (Foo foo in MyChildren) {
foreach (Foo f in foo.GetAll ()) {
yield return f;
}
}
}
在早期实现中,我返回一个 List 并使用 List.AddRange()
添加了 child-foos。
我的问题是使用yield的版本是否正确实现或者是否应该改进(特别是在性能方面)。 或者这只是不好,我应该坚持使用 List
(或 ReadOnlyCollections
)?
I've got a tree-like structure. Each element in this structure should be able to return a Enumerable of all elements it is root to. Let's call this method IEnumerable<Foo> GetAll()
. So if we have
A <-- topmost root
/ \
/ \
B C
/ \ / \
D E F G
a call to GetAll
on element C
returns {C, F, G}
(fixed order of elements would be nice, but is not needed). I guess everybody knew that already.
The current implementation of GetAll
looks like this:
public IEnumerable<Foo> GetAll ()
{
yield return this;
foreach (Foo foo in MyChildren) {
foreach (Foo f in foo.GetAll ()) {
yield return f;
}
}
}
In an earlier implementation, I returned a List and added the child-foos using List.AddRange()
.
My question is if the version using yield is correcly implemented or if it should be improved (esp. in terms of performance). Or is this just bad and I should stick to List
s (or ReadOnlyCollections
) instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果将递归展开到堆栈,则可以提高性能,因此您将只有一个迭代器:
You can improve performance if you unroll recurse to stack, so you will have only one iterator:
就性能而言,这当然并不理想 - 您最终会为大型树创建大量迭代器,而不是知道如何有效遍历的单个迭代器。
与此相关的一些博客文章:
值得注意的是,F# 具有与提议的“
yield foreach”等效的功能
”和“屈服!
”It's certainly not ideal in terms of performance - you end up creating a lot of iterators for large trees, instead of a single iterator which knows how to traverse efficiently.
Some blog entries concerning this:
It's worth noting that F# has the equivalent of the proposed "
yield foreach
" with "yield!
"更好的解决方案可能是创建一个递归遍历树的访问方法,并使用它来收集项目。
像这样的东西(假设是二叉树):
采用这种方法
A better solution might be to create a visit method that recursively traverses the tree, and use that to collect items up.
Something like this (assuming a binary tree):
Taking this approach
不,看起来不错。
看看我的博客文章,它可能有一些用处:)
No, that looks fine.
Have a look at my blog entry, it may be of some use :)
根据我之前的经验,使用 Yield 比创建 List 更有效。
如果您使用 .NET 3.5,此实现应该没问题。 但不要忘记
最后。 :-)
According to my prior experiences using yield is a lot more effective than creating a List.
If you're using .NET 3.5, this implementation should be fine. But don't forget the
At the end. :-)