我知道for i in arr
与arr.each
范围略有不同,每个人都说迭代器是可取的,但我不知道是否有任何情况下,当循环是可取的,为什么它是(因为迭代器更习惯)?有没有更好的选择,而不是每个Ruby?
回答
TL; DR
- 使用
for
循环性能的红宝石1.8 - 使用
for
循环到现有项目的标准 - 使用
each
环,以尽量减少副作用 - 身高:
each
环。
each
最小化副作用
for
和each
之间的主要差别是作用域。
each
函数占用一个块。块创建一个新的词法范围。这意味着在该函数范围内声明的任何变量在该函数之后将不再可用。
[1, 2, 3].each do |i|
a = i
end
puts a
# => NameErrror: undefined local variable or method `a' for main:Object
鉴于:
for i in [1, 2, 3]
a = i
end
puts a
# => 3
因此,使用each
语法最小化副作用的风险。
确定退出点?
这就是说,有些特殊情况下for
循环可能会有所帮助。具体来说,找出循环退出的位置。
for i in 1..3
a = i
break if i % 2 == 0
end
puts a
# => 0
有一种更好的方式来做到这一点,虽然:
a = (1..3).each do |i|
break i if i % 2 == 0
end
每一个都是(用Ruby 2.0)
Benchmark.bm(8) do |x|
x.report "For" do
max.times do
for i in 1..100
1 + 1
end
end
end
x.report "Each" do
max.times do
(1..100).each do |t|
1+1
end
end
end
end
红宝石2.0
user system total real
For 6.420000 0.000000 6.420000 ( 6.419870)
Each 5.830000 0.000000 5.830000 ( 5.829911)
快
的Ruby 1.8.6(机器慢)
user system total real
For 17.360000 0.000000 17.360000 (17.409992)
Each 21.130000 0.000000 21.130000 (21.250754)
基准2
如果你读了评论线索,有一个关于创造for
对象VS each
速度的讨论。 link provided有以下基准(尽管我已经清理了格式并修复了语法错误)。
b = 1..10e5
Benchmark.bmbm (10) do |x|
x.report "each {}" do
b.each { |r| r + 1 }
end
x.report "each do end" do
b.each do |r|
r + 1
end
end
x.report "for do end" do
for r in b do
r + 1
end
end
end
红宝石2.0
user system total real
each {} 0.150000 0.000000 0.150000 ( 0.144643)
each do end 0.140000 0.000000 0.140000 ( 0.143244)
for do end 0.150000 0.000000 0.150000 ( 0.147112)
的Ruby 1.8.6
user system total real
each {} 0.840000 0.000000 0.840000 ( 0.851634)
each do end 0.730000 0.000000 0.730000 ( 0.732737)
for do end 0.650000 0.000000 0.650000 ( 0.647186)
我明白这一点。我也知道内部Ruby转换为每个。但是我想知道是否还有什么情况会使用,而不是每个使用。 – p0deje
我发现当性能问题时,'for'循环可能是有益的。在Ruby中创建对象非常昂贵,并且可能会导致循环中的性能下降,并且会有很多迭代。 – thomthom
@thomthom你能提供显示这种情况的基准吗? – screenmutt
我已经写了几个插件SketchUp的红宝石API,我发现迭代大集合时(几何实体)我会得到更好的性能,通过一个for in
循环each
区块。
我认为这是因为for in
循环不会创建它的本地作用域,并且对象被重用,而不是像每个迭代中创建的那样,因为它将在each
循环中创建。
编辑:速度增益取决于Ruby版本。使用本文http://blog.shingara.fr/each-vs-for.html中使用的测试片段:
的Ruby 1.8.6:
user system total real
For 14.742000 0.000000 14.742000 (14.777000)
Each 18.190000 0.000000 18.190000 (18.194000)
的Ruby 2.0.0
user system total real
For 5.975000 0.000000 5.975000 ( 5.990000)
Each 5.444000 0.000000 5.444000 ( 5.438000)
事情大大因为旧的1.8提高。 6。 (尽管SketchUp扩展开发者仍然需要针对这个版本进行优化。)
1.8.6在很久以前就跌落支撑位。它也慢了很多,所以它用于比较是可疑的。也许1.8的最终版本。7会更合理,但1.9.3会更有意义。 –
诚然,如果你有控制Ruby平台。但是如果你为SketchUp编写扩展,你必须处理Ruby 1.8.6。 – thomthom
- 1. DotNetOpenAuth有没有更好的选择?
- 2. 有没有比CGContext更好的选择?
- 3. 有没有使用WCF RIA Serivces不是一个好的选择?
- 4. Ruby gsub:有没有更好的方法
- 5. 有没有更好的方式来写这个选择查询
- 6. 有没有更好的方法来做这个jQuery选择?
- 7. 有更好的选择sap.ui.commons.layout.MatrixLayout?
- 8. 如何选择所有列而不是每个硬编码?
- 9. 有没有更好的方法来索引多列而不是为每个排列创建一个索引?
- 10. 有没有更好的方式在列表中做广场而不是这个?
- 11. 有没有更好的方式来使用C++而不是轮询或选择异步TCP套接字?
- 12. jQuery没有选择每个图像
- 13. 有没有更好的选择,PI4J从UART读写raspbian?
- 14. 有没有更好的选择在Scala中实现Builder模式?
- 15. 有没有更好的选择使用CSS重置?
- 16. 有没有比在SQL中使用FOR XML更好的选择
- 17. 有没有更好的选择“列NOT IN(1,2,3)”?
- 18. UIScrollView错误,有没有更好的选择?
- 19. 收集事件 - 有没有比BindingList(T)更好的选择?
- 20. 在模型中使用“puts”有没有更好的选择?
- 21. 有没有更好的方法来编写后代选择器?
- 22. 是否有可能绑定选择选项上选择而不是更改
- 23. 这是表的有效用法吗?有更好的选择吗?
- 24. Ruby的Dir.glob有更快的选择吗?
- 25. PHP的SOAP扩展有没有一个好的选择?
- 26. 从多个表中选择多个选择还是从所有表中选择所有数据1次更好?
- 27. 有没有办法用ruby选择某个类的html元素?
- 28. 有选择地更新(而不是更新)字段
- 29. 有没有更好的方法来选择不是交互的兄弟的一个元素?
- 30. 更好的选择,而不是刀片的,UPDATE触发器
在Ruby中进行原型设计时,为了加快C语言扩展的速度,我发现使用更多C类成语有助于转换。但可能不是你正在寻找的答案。 。 。 –
此评论不是作为答案,只是提供一些额外的信息。根据[这个答案](http://stackoverflow.com/a/3294543/877472),'for'和'each'在后台使用'.each'。主要区别(根据来自同一问题的这个答案)(http://stackoverflow.com/a/3294561/877472))是如何将迭代器变量作用域的。最终,除了尼尔斯莱特的帖子之外,听起来似乎没有任何技术理由可以选择比其他更好的技术。 –