地图和Ruby之间的区别?

我已经Google了这个,并得到零星/矛盾的意见 – 是否有任何区别做一个map并在Ruby / Rails的数组collect

这些文档似乎没有提出任何build议,但是在方法或性能方面可能存在差异吗?

没有什么区别,事实上map是用C语言实现的,如rb_ary_collectenum_collect (例如,在一个数组和其他枚举上的map是有区别的,但mapcollect之间没有区别)。


为什么在Ruby中存在mapcollect mapfunction有许多不同语言的命名约定。 维基百科提供了一个概述 :

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

Ruby为Smalltalk世界的程序员提供了一个别名,让他们感到更加自在。


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

arrays是最常见的集合,因此优化其性能是合理的。 由于Ruby非常了解数组是如何工作的,所以不必调用each ,只能使用简单的指针操作 ,这种操作速度要快得多。

类似的优化存在一些数组方法,如zipcount

我被告知他们是一样的。

其实他们被logging在ruby-doc.org下的同一个地方:

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

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

为每个自我元素调用一次块。 创build一个包含块返回值的新数组。 另请参阅Enumerable#collect。
如果没有给出块,则返回一个枚举器。

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

Ruby别名方法Array#map to Array#collect; 它们可以互换使用。 (ruby僧侣)

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

  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

我做了一个基准testing,试着回答这个问题,然后find这个post,所以这里是我的发现(与其他答案略有不同)

以下是基准代码:

 require 'benchmark' h = { abc: 'hello', 'another_key' => 123, 4567 => 'third' } a = 1..10 many = 500_000 Benchmark.bm do |b| GC.start b.report("hash keys collect") do many.times do h.keys.collect(&:to_s) end end GC.start b.report("hash keys map") do many.times do h.keys.map(&:to_s) end end GC.start b.report("array collect") do many.times do a.collect(&:to_s) end end GC.start b.report("array map") do many.times do a.map(&:to_s) end end end 

我得到的结果是:

  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) 

也许别名不是免费的?