448

私はこれをグーグルで検索し、パッチのある/矛盾した意見を得ました-Ruby / Railsの配列で実行することmapと実行することの間に実際に違いはありますか?collect

ドキュメントは何も示唆していないようですが、おそらく方法やパフォーマンスに違いがありますか?

4

6 に答える 6

508

違いはありません。実際map、Cではrb_ary_collectandとして実装されていenum_collectます(たとえばmap、配列と他の列挙型には違いがありますが、との間に違いはありませんmapcollect


なぜ両方が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ます。

于 2011-03-10T02:24:34.003 に答える
54

私は彼らが同じであると言われました。

実際、それらは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"]
于 2011-03-10T02:23:32.203 に答える
15

collectとメソッドはとのcollect!エイリアスmapmap!あるため、互換的に使用できます。これを確認する簡単な方法は次のとおりです。

Array.instance_method(:map) == Array.instance_method(:collect)
 => true
于 2018-10-01T20:05:57.577 に答える
14

私はこの質問に答えるためにベンチマークテストを行い、次にこの投稿を見つけたので、ここに私の発見があります(他の答えとは少し異なります)

ベンチマークコードは次のとおりです。

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) 

おそらくエイリアスは無料ではありませんか?

于 2016-01-01T00:52:28.757 に答える
8

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;
}

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

于 2015-02-27T02:25:02.380 に答える
1

#collect実際にはのエイリアスです#map。つまり、2つの方法を同じように使用でき、同じ動作を実現できます。

于 2020-10-28T23:11:14.357 に答える