68

从这段代码中我不知道这两种方法之间的区别,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
4

7 回答 7

116

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"],因为它返回 self。

于 2011-03-18T04:57:43.067 回答
41

Array#each只需将每个元素放入块中,然后返回原始数组。Array#collect获取每个元素并将其放入返回的新数组中:

[1, 2, 3].each { |x| x + 1 }    #=> [1, 2, 3]
[1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]
于 2011-03-18T04:10:16.213 回答
6

each用于当您想要迭代数组并在每次迭代中做任何您想做的事情时。在大多数(命令式)语言中,这是程序员在需要处理列表时使用的“一刀切”的锤子。

对于更多的函数式语言,如果您不能以任何其他方式进行,则只能进行这种通用迭代。大多数时候,map 或 reduce 会更合适(在 ruby​​ 中收集和注入)

collect用于将一个数组转换为另一个数组时

inject用于将数组转换为单个值时

于 2011-03-18T04:27:39.087 回答
2

根据文档,这是两个源代码片段......

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()返回块返回的值(另见这篇关于元编程的博客文章)。

所以each只需生成并返回原始数组,同时collect创建一个新数组并将块的结果推入其中;然后它返回这个新数组。

源代码片段:每个收集

于 2011-03-18T04:18:45.357 回答
1

不同之处在于它返回的内容。在上面的示例 a == [nil,nil,nil]中(puts x.succ 的值)而b == ["L", "Z", "J"](原始数组)

在 ruby​​-doc 中,collect 执行以下操作:

为 self 的每个元素调用一次块。创建一个包含块返回值的新数组。

每个总是返回原始数组。说得通?

于 2011-03-18T04:14:32.373 回答
0

每个都是由包含 Enumerable 模块的所有类定义的方法。Object.each返回一个Enumerable::Enumerator对象。这是其他 Enumerable 方法用来遍历对象的方法。each每个类的方法表现不同。

在 Array 类中,当一个块被传递给 时each,它会在每个元素上执行块的语句,但最终返回 self。这在您不需要数组时很有用,但您可能只想从数组中选择元素并将 用作其他方法的参数。inspectmap返回一个新数组,其中包含每个元素上块执行的返回值。您可以使用map!andcollect!对原始数组执行操作。

于 2011-11-01T10:17:18.597 回答
0

我认为更容易理解它的方法如下:

nums = [1, 1, 2, 3, 5]
square = nums.each { |num| num ** 2 } # => [1, 1, 2, 3, 5]

相反,如果您使用收集:

square = nums.collect { |num| num ** 2 } # => [1, 1, 4, 9, 25]

另外,您可以使用它.collect!来改变原始数组。

于 2014-10-21T06:09:11.773 回答