Ruby中的每个和collect方法之间有什么不同

时间:2011-03-18 04:06:49

标签: ruby each collect

从这段代码中我不知道两种方法collecteach之间的区别。

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

7 个答案:

答案 0 :(得分:105)

Array#each接受一个数组并将给定的块应用于所有项目。它不会影响数组或创建新对象。它只是循环项目的一种方式。它也会返回自我。

  arr=[1,2,3,4]
  arr.each {|x| puts x*2}

打印2,4,6,8并返回[1,2,3,4]无论

Array#collectArray#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创建一个新数组并将块的结果推入其中;然后它返回这个新数组。

来源摘要:eachcollect

答案 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参数用于其他方法。 inspectmap返回一个新数组,其中包含每个元素上块执行的返回值。您可以使用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!来改变原始数组。