[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
私はこのコードを見ていますが、私の脳は10番がどのように結果になるかを登録していません。ここで何が起こっているのか説明してもらえますか?
最初のブロック引数をアキュムレータと考えることができます。ブロックの各実行の結果はアキュムレータに保存され、ブロックの次の実行に渡されます。上記のコードの場合、アキュムレータの結果をデフォルトで0に設定しています。ブロックを実行するたびに、現在の合計に指定された数値が加算され、結果がアキュムレータに格納されます。次のブロック呼び出しはこの新しい値を持ち、それに追加し、再び保存して、繰り返します。
プロセスの最後に、injectはアキュムレータを返します。この場合、配列内のすべての値の合計、つまり10です。
次に、オブジェクトの配列からハッシュを作成する別の簡単な例を示します。オブジェクトの文字列表現をキーにします。
[1,"a",Object.new,:hi].inject({}) do |hash, item|
hash[item.to_s] = item
hash
end
この場合、アキュムレーターを空のハッシュにデフォルト設定し、ブロックが実行されるたびにそれを設定します。ブロックの結果がアキュムレータに保存されるため、ブロックの最後の行としてハッシュを返す必要があることに注意してください。
inject
は、最初に値を取ります(0
)、ブロック)、リストの各要素に対してそのブロックを1回実行します。
result + element
)。これを説明する最も簡単な方法は、例として、各ステップがどのように機能するかを示すことです。これは、この結果をどのように評価できるかを示す想像上の一連の手順です。
[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
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
。
コードは、配列内の4つの要素を反復処理し、前の結果を現在の要素に追加します。
注入の()内に配置する番号は、開始位置を表します。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
彼らが言ったことは、しかし、あなたは常に「開始値」を提供する必要がないことにも注意してください:
[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つ少なくなります。
注入はブロックを適用します
result + element
配列内の各アイテムに。次の項目(「要素」)の場合、ブロックから返される値は「結果」です。 (パラメーターを使用して)呼び出し方は、「結果」はそのパラメーターの値で始まります。そのため、効果は要素を追加しています。
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
で動作します。
[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
[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に等しくなります。
このコードでは、開始値を渡さない可能性はありませんが、何が起こっているのかを説明するのに役立ちます。
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
ここから始めて、ブロックを取るすべてのメソッドを確認します。 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 }
要素インスペクターブロック内。
.inject()メソッドには別の形式があります。これは非常に役立ちます[4,5] .inject(&:+)これは、エリアのすべての要素を加算します
これはシンプルでわかりやすい説明です。
「初期値」は、最初は多少混乱するため忘れてください。
> [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
です。