Rubyでのマップと収集の違いは?


428

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

ドキュメントには、いずれかを示唆していないようですが、方法や性能の違いは、おそらくがあるのですか?


5
mapCode Golfでは推奨されています
Cary Swoveland、2016

1
理由の説明としてmapので、それが唯一である:すべてのために明白ではないかもしれませんCodeGolfで好まれ、collect4つの文字よりも長いmapが、機能は同じ。
Jochem Schulenklopper

2
悪魔の擁護者を演じるためだけに、私は個人的にcollectより読みやすく自然なものを見つけました。レコードを「収集」してXを実行するという考えは、レコードを「マッピング」してXを実行するよりも自然に理解できます。
2018年

回答:


480

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


なぜ両方を行うmapcollectRubyで存在しますか?map機能は、異なる言語で、多くの命名規則があります。ウィキペディアは概要を提供します

map関数は関数型プログラミング言語で作成されましたが、今日では多くの手続き型、オブジェクト指向、マルチパラダイム言語でもサポートされています(または定義される可能性があります)。C++の標準テンプレートライブラリではtransform、C#(3.0)ではと呼ばれています。 LINQライブラリは、という拡張メソッドとして提供されSelectます。マップは、Perl、Python、Rubyなどの高級言語で頻繁に使用される操作でもあります。操作はmap、これらの3つの言語すべてで呼び出されます。マップcollectエイリアスもRuby(Smalltalkから)で提供されています [強調は私のもの]。Common Lispはマップのような関数のファミリーを提供します。ここで説明する動作に対応するものを呼び出しますmapcar(-car は、CAR操作を使用したアクセスを示します)。

Rubyは、Smalltalkのプログラマーがよりくつろげるようにするためのエイリアスを提供します。


配列と列挙型の実装が異なるのはなぜですか?enumは一般化された反復構造です。つまり、Rubyが次の要素が何であるかを予測する方法はありません(無限のenumを定義できます。例についてはPrimeを参照してください)。したがって、連続する各要素を取得するために関数を呼び出す必要があります(通常、これはeachメソッドになります)。

配列は最も一般的なコレクションであるため、パフォーマンスを最適化することは妥当です。Rubyは配列がどのように機能するかについて多くを知っているので、呼び出す必要はありませんが、非常に高速eachな単純なポインター操作しか使用できません。

同様の最適化は、zipまたはのような多くの配列メソッドに対して存在しcountます。


14
@Mark Reedですが、SmallTalkを使用していないプログラマは、2つの異なる関数が単なるエイリアスであることが判明すると混乱します。上記のOPのような質問が発生します。
SasQ 2013

11
@SasQ同意しません-名前が1つだけの場合は全体的に良いと思います。しかし、Rubyには他にも多くのエイリアスがあり、エイリアシングの1つの特徴は、collectdetectinjectrejectselect(別名mapfindreducereject(エイリアスなし)の操作の間に、適切な名前が付けられていることです。)、およびfind_all)。
マークリード

5
確かに。どうやら、Rubyはエイリアス/シノニムをより多くの機会で使用しています。例えば、配列内の要素の数を用いて取得することができcountlengthまたはsize。異なる配列の同じ属性の言葉が、これにより、Rubyはあなたのコードのために最も適切な言葉を選ぶことができます:あなたがしたいん項目のはあなただ、収集、配列の、または現在の大きさの構造。基本的に、それらはすべて同じですが、正しい単語を選択すると、コードが読みやすくなる場合があります。これは、言語の優れた特性です。
Jochem Schulenklopper

52

彼らは同じだと聞いたことがあります。

実際、それらは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"]


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) 

おそらく、エイリアスは無料ではないのでしょうか?


1
これらの違いが重要かどうかはわかりません。再放送では、私は速度が異なる結果を得る(あなたのハッシュが収集遅く思える中であっても、あなたの配列は、コレクト速いようだ)
murb

11

collectそしてcollect!方法はへのエイリアスであるmapmap!彼らは互換的に使用できるように、。これを確認する簡単な方法は次のとおりです。

Array.instance_method(:map) == Array.instance_method(:collect)
 => true

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


4
ドキュメントがエイリアスであることを明示的に述べてほしい。現時点では、彼らは単にお互いを参照しており、どちらも少し異なる説明を持っています。
Chris Bloom
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.