6

このコードは、私が見つけた例から、インデックスに等しい配列内の要素の数をカウントします。しかし、どのように?

[4, 1, 2, 0].to_enum(:count).each_with_index{|elem, index| elem == index}

連鎖だけではできなかったし、連鎖内の評価の順番がややこしい。

私が理解しているのはEnumerable#count、ブロックが指定されている場合、真の値を生成する要素の数をカウントするオーバーロードを使用していることです。each_with_indexアイテムがそのインデックスと等しいかどうかのロジックがあることがわかります。

私が理解していないのはeach_with_index、 のブロック引数がどのようになるか、またはが で直接呼び出されたかのようcountに機能する理由です。存在する場合は、次のことができます。each_with_index[4,1,2,0]map_with_index

[4,1,2,0].map_with_index{ |e,i| e==i ? e : nil}.compact

しかし、この列挙可能なベースのスタイルを理解するのを手伝ってください-それはエレガントです!

4

3 に答える 3

4

より簡単な例から始めましょう。

[4, 1, 2, 0].count{|elem| elem == 4}
=> 1

ここでは、ブロックが配列の 1 つの要素 (最初の要素) に対して true を返すため、count メソッドは 1 を返します。

それでは、コードを見てみましょう。まず、to_enum を呼び出すと、Ruby は列挙子オブジェクトを作成します。

[4, 1, 2, 0].to_enum(:count)
=> #<Enumerator: [4, 1, 2, 0]:count>

ここで、列挙子は [4, 1, 2, 0] 配列と count メソッドを使用して反復の実行を待機しています。列挙子は保留中の反復のようなもので、後で発生するのを待っています。

次に、列挙子で each_with_index メソッドを呼び出し、ブロックを提供します。

...each_with_index{|elem, index| elem == index}

これにより、上で作成した列挙子オブジェクトの Enumerator#each_with_index メソッドが呼び出されます。Enumerator#each_with_index が行うことは、指定されたブロックを使用して保留中の反復を開始することです。ただし、反復からの値とともに、インデックス値もブロックに渡します。保留中の反復は count メソッドを使用するように設定されているため、列挙子は Array#count を呼び出します。これにより、配列の各要素が列挙子に戻され、列挙子はそれらをインデックスと共にブロックに渡します。最後に、Array#count は、上記の単純な例と同様に、真の値をカウントアップします。

私にとってこれを理解するための鍵は、Enumerator#each_with_index メソッドを使用していることです。

于 2013-10-21T22:25:43.160 に答える