2016-03-31 6 views
-3
これまでのところ、私が言うことができるように

array.rejectarray.select何もしない:Rubyでは、何が技術的に - ブロックなしでarray.rejectまたはarray.selectを実行しますか?

私が書くしようとしていたコードの場合
[nil, false, true].reject # Should have been reject.to_a for this example. 
=> [nil, false, true] 
[nil, false, true].select # Should have been select.to_a for this example. 
=> [nil, false, true] 

compactは私が必要なものだったが、ブロックせずに、私は非常に好奇心が強い理由rejectselect何もしない - 私は{ |e| e }のデフォルトのブロックを期待していたので、rejectcompactとなり、 '選択'は幾分奇妙なコンパクトになります。

デフォルトのブロックは何ですか?


編集:申し訳ありませんが、私は有益な何かを、私は遅延評価のいくつかの並べ替えを誘発し、選択/拒否の列挙になるだろう期待していたこれは、上記の式の両端の「.to_aを」オフ逃しました。私は通常このような事を避けるために&私の例を貼り付けます。

+6

[Enumerator](http://ruby-doc.org/core-2.1.5/Enumerator.html) – fl00r

+1

私のirbでは、[[nil、false、true] .reject =>#<列挙子: [nil、false、true]:reject> '、これはかなり質問に答えます。 –

+1

ブロックなしで選択すると、ドキュメントのように列挙子が返されます。なぜ元の配列以外のものになると思うのか分かりません。どうして拒否基準のない「拒否」が元の配列以外のものになってしまうのか、要素を拒否する理由がない場合はなぜ「コンパクト」になるのでしょうか? –

答えて

2

ブロックは、多くのRubyのメソッドのためのオプションです。ブロックが指定されていない場合、通常、列挙子が返されます。列挙子が必要な理由は少なくとも2つあります。

#1クラスEnumeratorのメソッドで列挙子を使用します。

次に例を示します。文字列内の文字の大文字と小文字を区別したいとします。一つの従来の方法は次のとおりです。

"oh happy day".each_char.with_index.map { |c,i| i.odd? ? c.upcase : c.downcase }.join 
    #=> "oH HaPpY DaY" 

いますが、代わりに書くことができる:

enum = [:odd, :even].cycle 
"oh happy day".each_char.map { |c| enum.next==:odd ? c.upcase : c.downcase }.join 

または多分

enum = [:upcase, :downcase].cycle 
"oh happy day".each_char.map { |c| c.send(enum.next) }.join 

Array#cycleEnumerator#nextのためのドキュメントを参照してください。上記の私の最初の例では連鎖方式

#2を使用列挙子、私が書いた:

"oh happy day".each_char.with_index.map... 

あなたはString#each_charEnumerator#with_indexのためのドキュメントを調べる場合は、両方の方法をすることができていることがわかりますブロックの有無にかかわらず使用されます。ここでは両方ともブロックなしで使用されています。これにより、3つの方法をに接続してとすることができます。

次のように戻り値を調べます。

enum0 = "oh happy day".each_char 
    #=> #<Enumerator: "oh happy day":each_char> 
enum1 = enum0.with_index 
    #=> #<Enumerator: #<Enumerator: "oh happy day":each_char>:with_index> 
enum2 = enum1.map 
    #=> #<Enumerator: #<Enumerator: #<Enumerator: 
    #  "oh happy day":each_char>:with_index>:map> 

あなたは「化合物」列挙子としてenum1enum2を考えたいかもしれません。

あなたはの戻り値を示しています。

[nil, false, true].reject 

がために:

#=> [nil, false, true] 

が、それは正しくありません。私たちが書く場合

#<Enumerator: [nil, false, true]:reject> 

:戻り値は、その後

enum = [nil, false, true].reject 

enum.each { |e| e } 
    #=> [nil, false] 

(これは、RubyのV2.3以来、私たちはenum.reject(&:itself)を書くことができ)。これはメソッドEnumerator#eachを使用し、の受信者がクラスArrayのインスタンスであるためenumArray#eachを呼び出すようにします。

+0

このような完全な答え、特に、リジェクト列挙に関する微妙な点は、その作成時点とは別のブロックによって操作されています。私はチェーン・イディオムをかなり頻繁に使用しますが、どのタイプが「ドットの間」で操作されているかは考慮していませんでした。 (私は自分自身が '.each {| e | e}'と書いているのに気づいていますが、猿のパッチを嫌うので、将来のバージョンでは '' it''メソッドのように定義しています。 Ruby。:) –

+0

@ android.weasel \tなぜあなたは '.each {| e | e} '? –

2

はそれのEnumeratorます:

en = [1,2,3].reject 
# => #<Enumerator: [1, 2, 3]:reject> 
en.each{|n| n == 1} 
# => [2, 3] 
+0

あなたは正しいです。私は通常、私の例をコピー・ペーストしますが、その時はありませんでした。私を混乱させていたのは、その列挙を.to_aを使って有用なことをすることに強制しようとすることでした。 @ CarySwovelandの返答は、 'each {| e | e}'を使って何かを有用にするために反復する必要があることを示しています。取得する。 –

関連する問題