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