Ruby和Ruby中的方法有什么不同?

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

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

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

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

Array#collectArray#map相同,它将所有项目的给定代码块应用并返回新数组。 简单地把“将一个序列的每个元素投射到一个新的forms”

  arr.collect {|x| x*2} 

退货[2,4,6,8]

并在您的代码

  a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K 

a是一个数组,但它实际上是一个puts x.succ[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”],因为它返回自我。

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

 [1, 2, 3].each { |x| x + 1 } #=> [1, 2, 3] [1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4] 

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

对于更多的函数式语言,如果您不能以其他方式进行,只能进行这种types的generics迭代。 大多数时候,无论是地图还是缩小都会更合适(收集并注入ruby)

collect是为了当你想把一个数组转换成另一个数组

inject是为了当你想把一个数组转换成一个单一的值

这里是两个源代码片断,根据文档 …

 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创build一个新的数组,并推动块的结果, 那么它返回这个新的数组。

源代码片段: 每个 收集

不同的是它返回。 在上面a == [nil,nil,nil]例子中, a == [nil,nil,nil] b == ["L", "Z", "J"] (原始数组)时a == [nil,nil,nil] (puts x.succ的值)

从ruby文档收集做以下几点:

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

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

每个类都是由所有包含Enumerable模块的类定义的方法。 Object.each返回一个Enumerable::Enumerator对象。 这是其他Enumerable方法用来迭代对象的内容。 each类的each方法的行为不同。

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

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

 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! 来改变原始数组。