【发布时间】:2013-03-28 11:38:20
【问题描述】:
似乎有很多方法可以在 Ruby 中循环遍历 Enumerable。 each、foreach或collect、map或其他类似方法有什么区别吗?
或者有什么理由我不应该在某些情况下使用某些方法?
【问题讨论】:
标签: ruby loops enums iterator iteration
似乎有很多方法可以在 Ruby 中循环遍历 Enumerable。 each、foreach或collect、map或其他类似方法有什么区别吗?
或者有什么理由我不应该在某些情况下使用某些方法?
【问题讨论】:
标签: ruby loops enums iterator iteration
collect/map 是等价的。它们与each 的不同之处在于each 只为每个元素执行块,而collect/map 返回一个数组,其中包含为每个元素调用块的结果。另一种说法可能是,each 应该对每个元素做一些事情,而 map 应该转换每个元素(将它映射到其他东西上) )。
您可以在任何使用each 的地方使用collect 或map,并且您的代码仍然可以工作。但它的效率可能会稍低一些,因为它将结果收集在一个数组中,除非您的 Ruby 实现意识到它不必费心创建一个数组,因为它从未使用过。
使用each 而不是map 或collect 的另一个原因是帮助任何阅读您的代码的人。如果我看到each,那么我可以说好吧,我们将使用数据的每个元素来做一些事情。如果我看到map,那么我希望看到基于旧数据的重新映射创建新数据。
关于 map 与 collect 我会说这是一个偏好问题,但你应该选择一个并坚持下去以保持一致性。
【讨论】:
each 应该对每个元素做一些事情,而map 应该对每个元素进行转换" 转换不也是一种做事的形式吗?区别不在于做什么,而在于返回什么。
使用pry和Rubinus(更容易阅读ruby代码)自己看看
$ pry
[1] pry(main)> cd Enumerable
[2] pry(Enumerable):1> show-method collect
From: .../rbx-head/kernel/common/enumerable18.rb @ line 4:
Owner: Enumerable
Visibility: public
Number of lines: 9
def collect
if block_given?
ary = []
each { |o| ary << yield(o) }
ary
else
to_a
end
end
[3] pry(Enumerable):1> show-method map
From: .../rbx-head/kernel/common/enumerable18.rb @ line 4:
Owner: Enumerable
Visibility: public
Number of lines: 9
def collect
if block_given?
ary = []
each { |o| ary << yield(o) }
ary
else
to_a
end
end
[4] pry(Enumerable):1>
所以不适合这两个。
map 和 collect 迭代一个集合。对于每个对象,它执行你的块然后收集结果。 each 方法不收集结果
【讨论】:
Array#collect(和Array#map)根据块中传递的代码返回一个新数组。 Array#each 对数组的每个元素执行一个操作(由块定义)。
我会像这样使用collect:
array = [1, 2, 3]
array2 = array.collect {|val| val + 1}
array.inspect # => "[1, 2, 3]"
array2.inspect # => "[2, 3, 4]"
和each 这样:
array = [1, 2, 3]
array.each {|val| puts val + 1 }
# >> 2
# >> 3
# >> 4
array.inspect # => "[1, 2, 3]"
【讨论】: