我用Google搜索并得到了不完整/矛盾的意见 - 在Ruby / Rails中对数组执行map
和执行collect
之间是否存在任何差异?
docs似乎没有任何暗示,但方法或表现可能存在差异吗?
答案 0 :(得分:453)
没有区别,实际上map
在C中实现为rb_ary_collect
和enum_collect
(例如,数组上的map
与其他任何内容之间存在差异枚举,但map
和collect
之间没有区别。
为什么Ruby中存在map
和collect
? 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,而且速度要快得多。
对于zip
或count
等多种数组方法,存在类似的优化。
答案 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;
}
答案 4 :(得分:4)
collect
和collect!
方法是map
和map!
的别名,因此可以互换使用。这是确认的简单方法:
Array.instance_method(:map) == Array.instance_method(:collect)
=> true
答案 5 :(得分:1)
#collect
实际上是#map
的别名。这意味着这两种方法可以互换使用,并且实现相同的行为。