我知道,因为我在arr中与arr.each范围略有不同,并且每个人都在说迭代器是可取的,但我想知道是否有任何情况下循环是可取的以及它为什么(因为迭代器更惯用)?
解决方法
TL; DR
>在Ruby 1.8中使用for循环来提高性能
>用于循环到现有项目中的标准
>使用每个循环以最小化副作用
>首选每个循环.
每个都可以减少副作用
范围和范围之间的主要区别是范围界定.
每个函数都占用一个块. Blocks创建了一个新的词法范围.这意味着在函数范围内声明的任何变量在函数后将不再可用.
[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,3] a = i end puts a # => 3
因此,使用每种语法可以最大限度地降低副作用的风险.
确定退出点?
这就是说,有一些特殊情况,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
Ruby 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
如果您阅读了评论记录,则会讨论创建对象的速度与每个对象的速度. 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
Ruby 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)