“为了”与“每个”在红宝石中
我刚刚有一个关于 Ruby 循环的快速问题。这两种迭代集合的方法有区别吗?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
只是想知道它们是否完全相同,或者是否存在细微的差异(可能当 @collection
为零时)。
I just had a quick question regarding loops in Ruby. Is there a difference between these two ways of iterating through a collection?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
Just wondering if these are exactly the same or if maybe there's a subtle difference (possibly when @collection
is nil).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
这是唯一的区别:
each:
for:
使用
for
循环,迭代器变量在块完成后仍然存在。对于each
循环,则不会,除非它在循环开始之前已被定义为局部变量。除此之外,
for
只是each
方法的语法糖。当 @collection 为 nil 时,两个循环都会抛出异常:
This is the only difference:
each:
for:
With the
for
loop, the iterator variable still lives after the block is done. With theeach
loop, it doesn't, unless it was already defined as a local variable before the loop started.Other than that,
for
is just syntax sugar for theeach
method.When
@collection
isnil
both loops throw an exception:请参阅“For 循环的弊端”了解详情很好的解释(考虑到变量范围有一个小小的差异)。
使用
each
被认为更惯用使用红宝石。See "The Evils of the For Loop" for a good explanation (there's one small difference considering variable scoping).
Using
each
is considered more idiomatic use of Ruby.您的第一个示例
更惯用。虽然 Ruby 支持像
for
和while
这样的循环结构,但块语法通常是首选。另一个细微的区别是,您在 for 循环中声明的任何变量都可以在循环外部使用,而迭代器块中的变量实际上是私有的。
Your first example,
is more idiomatic. While Ruby supports looping constructs like
for
andwhile
, the block syntax is generally preferred.Another subtle difference is that any variable you declare within a
for
loop will be available outside the loop, whereas those within an iterator block are effectively private.永远不要使用
for
,它可能会导致几乎无法追踪的错误。不要被愚弄,这与惯用代码或风格问题无关。 Ruby 的
for
实现存在严重缺陷,不应使用。下面是
for
引入错误的示例,进行打印
使用
%w{foo bar quz}.each { |n| ... }
打印为什么?
在
for
循环中,变量n
只定义一次,然后该定义将用于所有迭代。因此,每个块都引用相同的n
,在循环结束时其值为quz
。漏洞!在
each
循环中,为每次迭代定义一个新的变量n
,例如上面的变量n
被定义了三次。因此,每个块引用一个具有正确值的单独的n
。Never ever use
for
it may cause almost untraceable bugs.Don't be fooled, this is not about idiomatic code or style issues. Ruby's implementation of
for
has a serious flaw and should not be used.Here is an example where
for
introduces a bug,Prints
Using
%w{foo bar quz}.each { |n| ... }
printsWhy?
In a
for
loop the variablen
is defined once and only and then that one definition is use for all iterations. Hence each blocks refer to the samen
which has a value ofquz
by the time the loop ends. Bug!In an
each
loop a fresh variablen
is defined for each iteration, for example above the variablen
is defined three separate times. Hence each block refer to a separaten
with the correct values.还有一个区别:
来源:http://paulphilippov.com/ articles/enumerable-each-vs-for-loops-in-ruby
更清楚:http://www.ruby-forum.com/topic/179264#784884
One more difference:
source: http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
for more clear: http://www.ruby-forum.com/topic/179264#784884
看起来没有什么区别,
for
下面使用的是each
。就像贝亚德所说,每一个都更惯用。它对您隐藏了更多信息,并且不需要特殊的语言功能。
根据 Telemachus 的评论
for .. in ..
将迭代器设置在循环范围之外,因此在循环完成后保留
a
定义。而each
则不然。这是使用each
的另一个原因,因为 temp 变量的生存期较短。It looks like there is no difference,
for
useseach
underneath.Like Bayard says, each is more idiomatic. It hides more from you and doesn't require special language features.
Per Telemachus's Comment
for .. in ..
sets the iterator outside the scope of the loop, soleaves
a
defined after the loop is finished. Where aseach
doesn't. Which is another reason in favor of usingeach
, because the temp variable lives a shorter period.在“for”循环中,局部变量在每次循环后仍然有效。在“each”循环中,局部变量在每次循环后刷新。
In 'for' loop, local variable is still lives after each loop. In 'each' loop, local variable refreshes after each loop.
据我所知,使用块而不是语言内控制结构更惯用。
As far as I know, using blocks instead of in-language control structures is more idiomatic.
我只想就 Ruby 中的 for in 循环提出一个具体观点。它可能看起来像一个与其他语言类似的构造,但实际上它是一个与 Ruby 中所有其他循环构造类似的表达式。事实上,for in 就像each迭代器一样适用于Enumerable对象。
传递给 for in 的集合可以是具有 every 迭代器方法的任何对象。数组和散列定义了each 方法,许多其他Ruby 对象也定义了each 方法。 for/in 循环调用指定对象的each 方法。当迭代器产生值时,for 循环将每个值(或每组值)分配给指定的变量(或多个变量),然后执行主体中的代码。
这是一个愚蠢的例子,但说明了 for in 循环适用于任何具有each方法的对象,就像each迭代器的作用一样:
现在each迭代器:
如您所见,两者都响应each将值返回给块的方法。正如这里每个人所说,使用每个迭代器绝对比使用 for in 循环更可取。我只是想强调一点:for in 循环并没有什么神奇之处。它是一个调用集合的each 方法然后将其传递给其代码块的表达式。因此,在极少数情况下您需要使用 for in。几乎总是使用 every 迭代器(还有块作用域的额外好处)。
I just want to make a specific point about the for in loop in Ruby. It might seem like a construct similar to other languages, but in fact it is an expression like every other looping construct in Ruby. In fact, the for in works with Enumerable objects just as the each iterator.
The collection passed to for in can be any object that has an each iterator method. Arrays and hashes define the each method, and many other Ruby objects do, too. The for/in loop calls the each method of the specified object. As that iterator yields values, the for loop assigns each value (or each set of values) to the specified variable (or variables) and then executes the code in body.
This is a silly example, but illustrates the point that the for in loop works with ANY object that has an each method, just like how the each iterator does:
And now the each iterator:
As you can see, both are responding to the each method which yields values back to the block. As everyone here stated, it is definitely preferable to use the each iterator over the for in loop. I just wanted to drive home the point that there is nothing magical about the for in loop. It is an expression that invokes the each method of a collection and then passes it to its block of code. Hence, it is a very rare case you would need to use for in. Use the each iterator almost always (with the added benefit of block scope).
当使用 Ruby 的异步时,这一点非常重要。
将返回:
4 4 4 4 4
,因为i
不会为每次迭代重新定义。将返回:
0 1 2 3 4
,因为i
仅存在于其迭代块的范围内。在阅读其他答案时,其原因变得相当明显,但由于在线搜索查询中的异步问题不会返回任何提及此问题的结果,因此我将这个答案留在这里。
请勿将
for .. in ..
与async
结合使用!This is very important when using Ruby's
async
.Will return:
4 4 4 4 4
asi
is not re-defined for every iteration.Will return:
0 1 2 3 4
asi
only ever lives inside the scope of its iteration's block.The reason for this becomes fairly obvious when reading the other answers, but since online searches for this kind of problem with
async
in the query don't return any results mentioning this I left this answer here.Do not use
for .. in ..
in conjunction withasync
!