Ruby中的map和collect之间的区别?

时间:2011-03-10 02:19:40

标签: ruby arrays map collect

我用Google搜索并得到了不完整/矛盾的意见 - 在Ruby / Rails中对数组执行map和执行collect之间是否存在任何差异?

docs似乎没有任何暗示,但方法或表现可能存在差异吗?

6 个答案:

答案 0 :(得分:453)

没有区别,实际上map在C中实现为rb_ary_collectenum_collect(例如,数组上的map与其他任何内容之间存在差异枚举,但mapcollect之间没有区别。


为什么Ruby中存在mapcollect map函数在不同语言中有许多命名约定。 Wikipedia provides an overview

  

map函数起源于函数式编程语言,但现在支持(或可能定义)许多过程,面向对象和多范式语言:在C ++的标准模板库中,它被称为transform在C#(3.0)的LINQ库中,它作为名为Select的扩展方法提供。 Map也是Perl,Python和Ruby等高级语言中经常使用的操作。在所有这三种语言中,该操作都称为map Ruby(来自Smalltalk) [强调我的]提供了地图的collect别名。 Common Lisp提供了一系列类似地图的功能;与此处描述的行为相对应的一个称为mapcar(-car表示使用CAR操作的访问)。

Ruby为Smalltalk世界的程序员提供了一个别名,让他们有宾至如归的感觉。


为什么数组和枚举有不同的实现?枚举是一种通用的迭代结构,这意味着Ruby无法预测下一个元素是什么(你可以定义无限枚举,有关示例,请参阅Prime。因此,它必须调用一个函数来获取每个连续的元素(通常这将是each方法)。

阵列是最常见的集合,因此优化其性能是合理的。由于Ruby对数组的工作方式有很多了解,因此无需调用each,但只能使用简单pointer manipulation,而且速度要快得多。

对于zipcount等多种数组方法,存在类似的优化。

答案 1 :(得分:47)

我被告知他们是一样的。

实际上它们是在ruby-doc.org下的同一个地方记录的:

http://www.ruby-doc.org/core/classes/Array.html#M000249

  
      
  • ary.collect {| item | block}→new_ary
  •   
  • ary.map {| item | block}→new_ary
  •   
  • ary.collect→an_enumerator
  •   
  • ary.map→an_enumerator
  •   
     

为self的每个元素调用一次block。   创建一个包含块返回的值的新数组。   另见Enumerable#collect。
  如果没有给出块,则返回枚举器。

a = [ "a", "b", "c", "d" ]
a.collect {|x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
a                          #=> ["a", "b", "c", "d"]

答案 2 :(得分:11)

我做了一个基准测试试图回答这个问题,然后发现这篇文章所以这里是我的发现(与其他答案略有不同)

以下是基准代码:

                   user     system      total        real
hash keys collect  0.540000   0.000000   0.540000 (  0.570994)
hash keys map      0.500000   0.010000   0.510000 (  0.517126)
array collect      1.670000   0.020000   1.690000 (  1.731233)
array map          1.680000   0.020000   1.700000 (  1.744398) 

我得到的结果是:

{{1}}

也许别名不是免费的?

答案 3 :(得分:7)

Ruby将方法Array#map别名为Array#collect;它们可以互换使用。 (Ruby Monk)

换句话说,相同的源代码:

               static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;

RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
    rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
}
return collect;
}

http://ruby-doc.org/core-2.2.0/Array.html#method-i-map

答案 4 :(得分:4)

collectcollect!方法是mapmap!的别名,因此可以互换使用。这是确认的简单方法:

Array.instance_method(:map) == Array.instance_method(:collect)
 => true

答案 5 :(得分:1)

#collect实际上是#map的别名。这意味着这两种方法可以互换使用,并且实现相同的行为。