web-dev-qa-db-ja.com

注入方法の簡単な説明が必要

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

私はこのコードを見ていますが、私の脳は10番がどのように結果になるかを登録していません。ここで何が起こっているのか説明してもらえますか?

133
hightide

最初のブロック引数をアキュムレータと考えることができます。ブロックの各実行の結果はアキュムレータに保存され、ブロックの次の実行に渡されます。上記のコードの場合、アキュムレータの結果をデフォルトで0に設定しています。ブロックを実行するたびに、現在の合計に指定された数値が加算され、結果がアキュムレータに格納されます。次のブロック呼び出しはこの新しい値を持ち、それに追加し、再び保存して、繰り返します。

プロセスの最後に、injectはアキュムレータを返します。この場合、配列内のすべての値の合計、つまり10です。

次に、オブジェクトの配列からハッシュを作成する別の簡単な例を示します。オブジェクトの文字列表現をキーにします。

[1,"a",Object.new,:hi].inject({}) do |hash, item|
  hash[item.to_s] = item
  hash
end

この場合、アキュムレーターを空のハッシュにデフォルト設定し、ブロックが実行されるたびにそれを設定します。ブロックの結果がアキュムレータに保存されるため、ブロックの最後の行としてハッシュを返す必要があることに注意してください。

197
Drew Olson

injectは、最初に値を取ります(0)、ブロック)、リストの各要素に対してそのブロックを1回実行します。

  1. 最初の反復で、開始値として指定した値とリストの最初の要素を渡し、ブロックが返した値(この場合はresult + element)。
  2. 次に、ブロックを再度実行し、最初の繰り返しの結果を最初の引数として渡し、リストの2番目の要素を2番目の引数として渡し、結果を再度保存します。
  3. リストのすべての要素を使い果たすまで、このように続けます。

これを説明する最も簡単な方法は、例として、各ステップがどのように機能するかを示すことです。これは、この結果をどのように評価できるかを示す想像上の一連の手順です。

[1, 2, 3, 4].inject(0) { |result, element| result + element }
[2, 3, 4].inject(0 + 1) { |result, element| result + element }
[3, 4].inject((0 + 1) + 2) { |result, element| result + element }
[4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
[].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
(((0 + 1) + 2) + 3) + 4
10
81
Brian Campbell

Injectメソッドの構文は次のとおりです。

inject (value_initial) { |result_memo, object| block }

上記の例を解決しましょう。

[1, 2, 3, 4].inject(0) { |result, element| result + element }

出力として1が得られます。

したがって、開始する前に、各変数に格納されている値を見てみましょう。

結果=ゼロはinject(value)でから来ました

element = 1これは配列の最初の要素です。

オーケー!!!それでは、上記の例を理解してみましょう

ステップ:1 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }

ステップ:2 [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }

ステップ:3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }

ステップ:4 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }

ステップ:5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }

ここに ボールドイタリック 値は配列からフェッチされる要素であり、単純に 大胆な 値は結果の値です。

#injectメソッドの#Ruby

26
Vishal Nagda

コードは、配列内の4つの要素を反復処理し、前の結果を現在の要素に追加します。

  • 1 + 2 = 3
  • 3 + 3 = 6
  • 6 + 4 = 10
18
John Topley

注入の()内に配置する番号は、開始位置を表します。0または1000です。パイプ内には、2つのプレースホルダー| x、y |があります。 x = .inject( 'x')の内部にある数字。秒はオブジェクトの各反復を表します。

[1, 2, 3, 4].inject(5) { |result, element| result + element } # => 15

1 + 5 = 6 2 + 6 = 8 3 + 8 = 11 11 + 4 = 15

14
Stuart G

彼らが言ったことは、しかし、あなたは常に「開始値」を提供する必要がないことにも注意してください:

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

と同じです

[1, 2, 3, 4].inject { |result, element| result + element } # => 10

やってみて、待ってます。

引数が注入に渡されない場合、最初のtwo要素が最初の反復に渡されます。上記の例では、結果は1で、要素は最初に2であるため、ブロックに対する呼び出しは1つ少なくなります。

14
Mike Woodhouse

注入はブロックを適用します

result + element

配列内の各アイテムに。次の項目(「要素」)の場合、ブロックから返される値は「結果」です。 (パラメーターを使用して)呼び出し方は、「結果」はそのパラメーターの値で始まります。そのため、効果は要素を追加しています。

6
Sam Hoice

tldr;injectは、1つの重要な点でmapと異なります。injectはブロックの最後の実行の値を返しますが、mapは、反復処理された配列を返します。

それ以上最初のパラメーター(この場合はresult)を介して次の実行に渡される各ブロック実行の値。その値((0) part)。

上記の例は、mapを使用して次のように記述できます。

result = 0 # initialize result
[1, 2, 3, 4].map { |element| result += element }
# result => 10

同じ効果ですが、injectの方が簡潔です。

評価はmapブロックで行われるのに対し、評価はinjectブロックで行われます。

どの方法を選択するかは、resultに必要なスコープによって異なります。いつnotを使用するかは、次のようになります。

result = [1, 2, 3, 4].inject(0) { |x, element| x + element }

「Lookie me、私はそれを1行にまとめただけです」と思われるかもしれませんが、xには既にresultで動作します。

6
IAmNaN
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

以下と同等です。

def my_function(r, e)
  r+e
end

a = [1, 2, 3, 4]
result = 0

a.each do |value|
  result = my_function(result, value)
end
4
Fred Willmore

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

簡単な英語では、この配列([1,2,3,4])。 4つの要素(1、2、3、および4)があるため、この配列を4回繰り返します。 injectメソッドには1つの引数(数値0)があり、その引数を1番目の要素に追加します(0 +1。これは1に等しい)。 「結果」に1が保存されます。次に、その結​​果(1)を次の要素(1 +2。これは3)に追加します。 Thisは結果として保存されます。続けてください:3 + 3は6に等しく、最後に6 + 4は10に等しくなります。

3
Maddie

このコードでは、開始値を渡さない可能性はありませんが、何が起こっているのかを説明するのに役立ちます。

def incomplete_inject(enumerable, result)
  enumerable.each do |item|
    result = yield(result, item)
  end
  result
end

incomplete_inject([1,2,3,4], 0) {|result, item| result + item} # => 10
2
Andrew Grimm

ここから始めて、ブロックを取るすべてのメソッドを確認します。 http://Ruby-doc.org/core-2.3.3/Enumerable.html#method-i-inject

あなたを混乱させるのはブロックですか、それともメソッドに値があるのですか?いい質問ですね。そこでの演算子メソッドは何ですか?

result.+

それは何から始まりますか?

#inject(0)

これはできますか?

[1, 2, 3, 4].inject(0) { |result, element| result.+ element }

これは機能しますか?

[1, 2, 3, 4].inject() { |result = 0, element| result.+ element }

私は、配列のすべての要素を単純に合計し、ドキュメントに表示されるメモに数値を生成するという考えに基づいています。

これはいつでもできます

 [1, 2, 3, 4].each { |element| p element }

配列の列挙可能要素が繰り返し処理されることを確認します。それが基本的な考え方です。

インジェクトまたはリデュースするだけで、送信されるメモまたはアキュムレーターが提供されます。

結果を得ることができます

[1, 2, 3, 4].each { |result = 0, element| result + element }

しかし、何も返されないので、これは以前と同じように機能します

[1, 2, 3, 4].each { |result = 0, element| p result + element }

要素インスペクターブロック内。

1

.inject()メソッドには別の形式があります。これは非常に役立ちます[4,5] .inject(&:+)これは、エリアのすべての要素を加算します

0

これはシンプルでわかりやすい説明です。

「初期値」は、最初は多少混乱するため忘れてください。

> [1,2,3,4].inject{|a,b| a+b}
=> 10

上記を理解できます:1,2,3,4の間に「追加マシン」を注入しています。つまり、1♫2♫3♫4であり、♫は加算機です。したがって、1 + 2 + 3 + 4と同じであり、10です。

実際にそれらの間に+を挿入できます:

> [1,2,3,4].inject(:+)
=> 10

それは、1,2,3,4の間に+を挿入し、1 + 2 + 3 + 4で10になるようなものです。:+は、シンボルの形式で+を指定するRubyの方法です。

これは非常に理解しやすく、直感的です。そして、それがどのように機能するかを段階的に分析したい場合は、1と2を取り、それらを追加し、結果が得られたら最初に保存し(3)、次は保存します値3および配列要素3はa + bプロセスを通過します。これは6であり、現在この値を格納しています。6および4はa + bプロセスを通過し、10です。

((1 + 2) + 3) + 4

そして、10です。「初期値」0は、単に「ベース」です。多くの場合、それは必要ありません。 1 * 2 * 3 * 4が必要な場合を想像してください

[1,2,3,4].inject(:*)
=> 24

完了です。 1で全体を乗算するために1の「初期値」は必要ありません。

他の言語に精通している場合は、reduceまたはfoldです。

0
Nick