私はこれをグーグルして、曖昧で矛盾する意見を得ました - Ruby/Railsの配列に対してmap
を実行することとcollect
を実行することの間に実際に違いはありますか?
docs は何も示唆していないようですが、おそらく方法やパフォーマンスに違いはありますか?
違いはありません。実際、map
はCでrb_ary_collect
とenum_collect
として実装されています(たとえば、配列のmap
と他のenumの間に違いはありますが、map
とcollect
の間に違いはありません)。
Rubyにmap
とcollect
の両方が存在するのはなぜですか?map
関数には、さまざまな言語で多くの命名規則があります。 ウィキペディアに概要があります :
Map関数は関数型プログラミング言語で作られましたが、今日では多くの手続き型、オブジェクト指向、そしてマルチパラダイム言語でもサポートされています(あるいは定義されるかもしれません):C++の標準テンプレートライブラリではC#(3.0)では
transform
と呼ばれています。 ■LINQライブラリ。これはSelect
という拡張メソッドとして提供されています。 MapはPerl、Python、Rubyなどの高水準言語でもよく使われる操作です。この3つの言語すべてで、操作はmap
と呼ばれます。 mapのcollect
エイリアスも(Smalltalkの)Rubyで提供されています[強調]。 Common LISPは地図のような機能のファミリーを提供します。ここで説明した動作に対応するものはmapcar
と呼ばれます(-carはCAR操作を使用したアクセスを示します)。
Rubyは、Smalltalkの世界から来たプログラマーに、くつろいだ雰囲気を提供するためのエイリアスを提供します。
配列とenumに異なる実装があるのはなぜですか?enumは一般化された繰り返し構造であり、Rubyが何を予測できるのかがわかりません。次の要素にすることができます(あなたは無限のenumを定義することができます。例として Prime を参照してください)。したがって、連続した各要素を取得するために関数を呼び出す必要があります(通常、これはeach
メソッドになります)。
配列は最も一般的なコレクションなので、パフォーマンスを最適化するのが妥当です。 Rubyは配列がどのように動作するかについて多くのことを知っているので、each
を呼び出す必要はありませんが、単純な ポインタ操作 のみを使うことができます。これはかなり速いです。
Zip
やcount
のようないくつかのArrayメソッドに対しても同様の最適化が存在します。
私は言われました 彼らは同じです。
実際、それらは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
Selfの各要素に対して1回blockを呼び出します。ブロックによって返された値を含む新しい配列を作成します。 Enumerable#collectも参照してください。
ブロックが指定されていない場合は、代わりに列挙子が返されます。a = [ "a", "b", "c", "d" ] a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"] a #=> ["a", "b", "c", "d"]
私はこの質問に答えてみるためにベンチマークテストをしました、そしてこの投稿を見つけたのでここに私の発見があります(他の回答とは少し異なります)
これがベンチマークコードです。
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)
おそらくエイリアスは無料ではありませんか?
Rubyは、メソッドArray#mapをArray#collectにエイリアスします。それらは互換的に使用できます。 (ルビーモンク)
言い換えれば、同じソースコード:
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;
}
collect
メソッドおよびcollect!
メソッドは、map
およびmap!
のエイリアスであるため、これらを交換して使用することができます。これを確認する簡単な方法は次のとおりです。
Array.instance_method(:map) == Array.instance_method(:collect)
=> true