68

collectこのコードから、2つの方法の違いはわかりませんeach

a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K 
print  a.class  #=> Array

b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
print  b.class #=> Array
4

7 に答える 7

116

Array#each配列を取り、指定されたブロックをすべてのアイテムに適用します。配列に影響を与えたり、新しいオブジェクトを作成したりすることはありません。これは、アイテムをループする方法にすぎません。また、それは自己を返します。

  arr=[1,2,3,4]
  arr.each {|x| puts x*2}

2,4,6,8を出力し、何があっても[1,2,3,4]を返します

Array#collectと同じでArray#map、指定されたコードブロックをすべてのアイテムに適用し、新しい配列を返します。単に「シーケンスの各要素を新しい形式に投影する」

  arr.collect {|x| x*2}

[2,4,6,8]を返します

そしてあなたのコードで

 a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K 

aは配列ですが、実際にはNilの[nil、nil、nil]の配列です。これは、 (M AA Kを出力する場合でも)がputs x.succ返されるためです。nil

 b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K

アレイでもあります。ただし、自己を返すため、その値は["L"、 "Z"、"J"]です。

于 2011-03-18T04:57:43.067 に答える
41

Array#each各要素を取得してブロックに配置し、元の配列を返します。Array#collect各要素を受け取り、それを新しい配列に入れて返します。

[1, 2, 3].each { |x| x + 1 }    #=> [1, 2, 3]
[1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]
于 2011-03-18T04:10:16.213 に答える
6

each配列を反復処理し、各反復で必要なことを実行する場合に使用します。ほとんどの(命令型)言語では、これは、リストを処理する必要があるときにプログラマーが到達する「1つのサイズですべてに対応する」ハンマーです。

より機能的な言語の場合、他の方法で実行できない場合にのみ、この種の一般的な反復を実行します。ほとんどの場合、マップまたはリデュースのいずれかがより適切です(ルビーで収集して注入します)

collectある配列を別の配列に変換したい場合に使用します

inject配列を単一の値に変換したい場合に使用します

于 2011-03-18T04:27:39.087 に答える
2

ドキュメントによると、2つのソースコードスニペットがあります...

VALUE
rb_ary_each(VALUE ary)
{
    long i;

    RETURN_ENUMERATOR(ary, 0, 0);
    for (i=0; i<RARRAY_LEN(ary); i++) {
        rb_yield(RARRAY_PTR(ary)[i]);
    }
    return ary;
}

# .... .... .... .... .... .... .... .... .... .... .... ....

static VALUE
rb_ary_collect(VALUE ary)
{
    long i;
    VALUE collect;

    RETURN_ENUMERATOR(ary, 0, 0);
    collect = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
    }
    return collect;
}

rb_yield()ブロックによって返される値を返します(メタプログラミングに関するこのブログ投稿も参照してください)。

したがって、元の配列を生成して返すeachだけで、新しい配列を作成してブロックの結果をその配列にプッシュします。次に、この新しい配列を返します。collect

ソーススニペット:それぞれ収集

于 2011-03-18T04:18:45.357 に答える
1

違いはそれが返すものです。上記の例 a == [nil,nil,nil]では、(puts x.succの値)while b == ["L", "Z", "J"](元の配列)

ruby-docから、collectは次のことを行います。

自己の要素ごとに1回ブロックを呼び出します。ブロックによって返される値を含む新しい配列を作成します。

それぞれが常に元の配列を返します。意味がありますか?

于 2011-03-18T04:14:32.373 に答える
0

それぞれは、Enumerableモジュールを含むすべてのクラスによって定義されたメソッドです。オブジェクトObject.eachを返します。Enumerable::Enumeratorこれは、他のEnumerableメソッドがオブジェクトを反復処理するために使用するものです。each各クラスのメソッドの動作は異なります。

Arrayクラスでは、ブロックがに渡されるとeach、各要素に対してブロックのステートメントが実行されますが、最終的にはselfが返されます。これは、配列が必要ないが、配列から要素を選択したい場合に便利です。他のメソッドへの引数としてasを使用します。inspectそしてmap、各要素のブロックの実行の戻り値を含む新しい配列を返します。map!およびを使用collect!して、元の配列に対して操作を実行できます。

于 2011-11-01T10:17:18.597 に答える
0

私はそれを理解するためのより簡単な方法は以下のようになると思います:

nums = [1, 1, 2, 3, 5]
square = nums.each { |num| num ** 2 } # => [1, 1, 2, 3, 5]

代わりに、collectを使用する場合:

square = nums.collect { |num| num ** 2 } # => [1, 1, 4, 9, 25]

.collect!さらに、元の配列を変更するために使用できます。

于 2014-10-21T06:09:11.773 に答える