从这段代码中我不知道两种方法collect
和each
之间的区别。
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
print a.class #=> Array
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
print b.class #=> Array
答案 0 :(得分:105)
Array#each
接受一个数组并将给定的块应用于所有项目。它不会影响数组或创建新对象。它只是循环项目的一种方式。它也会返回自我。
arr=[1,2,3,4]
arr.each {|x| puts x*2}
打印2,4,6,8并返回[1,2,3,4]无论
Array#collect
与Array#map
相同,它在所有项目上应用给定的代码块并返回新数组。只需将序列中每个元素的'项目投入新表格
arr.collect {|x| x*2}
返回[2,4,6,8]
并在您的代码中
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
a是一个数组,但它实际上是一个由Nil [nil,nil,nil] 组成的数组,因为puts x.succ
返回nil
(即使它打印出来) M AA K)。
并且
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
也是一个数组。但它的价值在于[" L"" Z"," J"],因为它会返回自我。
答案 1 :(得分:37)
Array#each
只取每个元素并将其放入块中,然后返回原始数组。 Array#collect
获取每个元素并将其放入一个返回的新数组中:
[1, 2, 3].each { |x| x + 1 } #=> [1, 2, 3]
[1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]
答案 2 :(得分:5)
each
用于迭代数组,并在每次迭代中执行任何操作。在大多数(命令式)语言中,这是程序员在您需要处理列表时所达到的“一刀切”的锤子。
对于更多功能语言,如果不能以任何其他方式执行此操作,则只执行此类通用迭代。大多数情况下,map或reduce更合适(收集并注入红宝石)
collect
用于何时将一个数组转换为另一个数组
inject
用于何时将数组转换为单个值
答案 3 :(得分:2)
根据docs ...
,以下是两个源代码段VALUE
rb_ary_each(VALUE ary)
{
long i;
RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_PTR(ary)[i]);
}
return ary;
}
# .... .... .... .... .... .... .... .... .... .... .... ....
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_ENUMERATOR(ary, 0, 0);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
}
return collect;
}
rb_yield()
返回块返回的值(see also this blog post on metaprogramming)。
所以each
只是产生并返回原始数组,而collect
创建一个新数组并将块的结果推入其中;然后它返回这个新数组。
答案 4 :(得分:1)
不同之处在于它的回报。在上面的例子中
a == [nil,nil,nil]
(puts x.succ的值)b == ["L", "Z", "J"]
(原始数组)
在ruby-doc中,collect执行以下操作:
为每个元素调用一次block 自。创建一个包含的新数组 块返回的值。
每个都会返回原始数组。有意义吗?
答案 5 :(得分:0)
每个都是由包含Enumerable模块的所有类定义的方法。 Object.each
会返回Enumerable::Enumerator
个对象。这是其他Enumerable方法用于迭代对象的内容。每个类的each
方法行为不同。
在Array类中,当一个块传递给each
时,它会对每个元素执行块的语句,但最后会返回self。当你不需要数组时,这很有用,但是你可能只想从数组中选择元素并将as参数用于其他方法。 inspect
和map
返回一个新数组,其中包含每个元素上块执行的返回值。您可以使用map!
和collect!
对原始阵列执行操作。
答案 6 :(得分:0)
我认为理解它的更简单方法如下:
nums = [1, 1, 2, 3, 5]
square = nums.each { |num| num ** 2 } # => [1, 1, 2, 3, 5]
相反,如果你使用collect:
square = nums.collect { |num| num ** 2 } # => [1, 1, 4, 9, 25]
而且,您可以使用.collect!
来改变原始数组。