each
循环而不是for
循环?它们的时间复杂度有区别吗,还是只是语法上的差异?是的,这两种迭代方式是不同的,但希望这个计算能有所帮助。
require 'benchmark'
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
a.each { |x| sum += x }
}
这需要5.866932秒
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
for x in a
sum += x
end
}
这需要6.146521秒。
虽然这不是一个正确的基准测试方法,但也有其他一些限制。但在单台计算机上,每个似乎比for循环快一点。
for
被展开成 each
,我不认为它们之间会有什么区别。如果有的话,for
应该会稍微快一点,因为它不需要分配一个新的局部作用域,而在 for
循环内声明的变量会污染外部作用域,而传递给 each
的块具有自己的作用域。 - Jörg W Mittagfor
真的是 each
的语法糖吗?而且,顺便说一下,出于同样的原因,我也希望 for
更快。我解释了相反的观察结果,Ruby 开发人员更注重优化 each
而不是 for
。 - Boris Stitnickyfor var1,var2 in expression; do_something end
被评估为expression.each do |var1,var2| do_something end
,除了该块没有自己的作用域。尝试def (a = Object.new).each; p 'each called'; yield 42 end; for e in a; p e end # 'each called' # 42 # => 42
。 - Jörg W MittagThe variable referencing an item in iteration is temporary and does not have significance outside of the iteration. It is better if it is hidden from outside of the iteration. With external iterators, such variable is located outside of the iteration block. In the following, e
is useful only within do
... end
, but is separated from the block, and written outside of it; it does not look easy to a programmer:
for e in [:foo, :bar] do
...
end
With internal iterators, the block variable is defined right inside the block, where it is used. It is easier to read:
[:foo, :bar].each do |e|
...
end
This visibility issue is not just for a programmer. With respect to visibility in the sense of scope, the variable for an external iterator is accessible outside of the iteration:
for e in [:foo] do; end
e # => :foo
whereas in internal iterator, a block variable is invisible from outside:
[:foo].each do |e|; end
e # => undefined local variable or method `e'
The latter is better from the point of view of encapsulation.
When you want to nest the loops, the order of variables would be somewhat backwards with external iterators:
for a in [[:foo, :bar]] do
for e in a do
...
end
end
but with internal iterators, the order is more straightforward:
[[:foo, :bar]].each do |a|
a.each do |e|
...
end
end
With external iterators, you can only use hard-coded Ruby syntax, and you also have to remember the matching between the keyword and the method that is internally called (for
calls each
), but for internal iterators, you can define your own, which gives flexibility.
for
循环的问题,这与我的早期问题类似,即<my earlier question whethe for loop is a trap>。[1, 2, 3].each { |e| puts e * 10 }
[1, 2, 3].map { |e| e * 10 )
# etc., see Array and Enumerable documentation for more iterator methods.
Enumerator
,您应该努力理解它。while
、until
和for
循环的Pascal式循环。for y in [1, 2, 3]
puts y
end
x = 0
while x < 3
puts x; x += 1
end
# same for until loop
if
和unless
一样,while
和until
也有它们的尾部形式,例如:a = 'alligator'
a.chop! until a.chars.last == 'g'
#=> 'allig'
class Object
def method_missing sym
s = sym.to_s
if s.chars.last == 'g' then s else eval s.chop end
end
end
alligator
#=> "allig"
除了可读性问题外,for
循环在Ruby领域中迭代,而each
从本地代码中进行迭代,因此原则上当迭代数组中的所有元素时,each
应更有效率。
使用each循环:
arr.each {|x| puts x}
使用for循环进行循环:
for i in 0..arr.length
puts arr[i]
end
for
比each
更合适吗? - Stefanfor
可能会使你的代码高度低效。 - Claudi