| m、k | ある種のことは私を失望させます。これは優先順位と関係がありますか?mは0(または一部の言語では1)を表し、kは配列/ハッシュの最後を表しますか?
では、なぜ人々は.inject()に数値を入れるのでしょうか?
あるいは、これを使用する方法と、その価値を正確に知る簡単な方法はありますか?この質問から判断すると、私がどのプログラミング言語にもかなり慣れていないことを皆さんが知っていることを願っています。Rubyが私の最初の選択でした。
| m、k | ある種のことは私を失望させます。これは優先順位と関係がありますか?mは0(または一部の言語では1)を表し、kは配列/ハッシュの最後を表しますか?
では、なぜ人々は.inject()に数値を入れるのでしょうか?
あるいは、これを使用する方法と、その価値を正確に知る簡単な方法はありますか?この質問から判断すると、私がどのプログラミング言語にもかなり慣れていないことを皆さんが知っていることを願っています。Rubyが私の最初の選択でした。
例を試してみましょう。
numbers = [ 3, 1, 4, 1, 5, 9 ]
sum = numbers.inject(0) do |prefix_sum, number|
prefix_sum + number
end
#inject1 つの引数と 1 つのブロックを取ります。ブロックは 2 つの値を取り、新しい値を返す必要があります。
上記の例では、 への引数#injectは0で、ブロックはdo |prefix_sum, number| prefix_sum + number endです。ブロックに渡される値は、 と の 2 つのマーカーの間に名前が付けられ|ます。prefix_sumnumber
enumerable#injectが呼び出された各値は、2 番目の値としてブロックに順番に渡されます。この例でnumberは3、次に1、次に4、次に1、次に5、最後になり9ます。したがって、この例では、ブロックは 6 回呼び出されます。の位置ごとに 1 回numbers。
ブロック (ここでは という名前prefix_sum) に渡される最初の値は、通常、アキュムレータと呼ばれます。その初期値、つまりブロックが によって最初に呼び出されたときに使用される値は、に#inject渡される引数#inject(この例では0) によって設定されます。ブロックの戻り値は、ブロックprefix_sumの次の呼び出しのアキュムレータ ( ) の値を決定します。
処理する要素がなくなると、アキュムレータの値が返されます (ここでは に格納されsumます)。
それでは、それを見てみましょう:
#inject受信0し、私たちのブロック。#injectブロックを呼び出し、(アキュムレータの初期値) と(最初の配列値)にバインドprefix_sumします。0number30+3し3、それを返します。#injectブロックを呼び出し、(戻り値) と( 2 番目の配列値)にバインドprefix_sumします。3number13+1し4、それを返します。#injectブロックを呼び出し、(戻り値) と( 3 番目の配列値)にバインドprefix_sumします。4number44+4し8、それを返します。#injectブロックを呼び出し、(戻り値) と( 4 番目の配列値)にバインドprefix_sumします。8number18+1し9、それを返します。#injectブロックを呼び出し、(戻り値) と( 5 番目の配列値)にバインドprefix_sumします。9number59+5し14、それを返します。#injectブロックを呼び出し、(戻り値) と( 6 番目の配列値)にバインドprefix_sumします。14number914+9し23、それを返します。#inject返し23、その値になるようにバインドsumします。inject は、項目のリストに対する操作を括弧で囲んだものと見なすことができます。この例では、次の計算を行います。
((((((0 + 3) + 1) + 4) + 1) + 5) + 9)
これにより、通常は引数のペアでのみ動作する操作を取り、それをリストに適用できます。
ブロック引数とメソッド引数を混同しているようです。
inject() メソッドに渡される人数は、|m,k| を使用するときの "m" の初期値を決定するメソッド引数です。ブロックのために。m と k という名前をどこで見たのか、またはなぜそのような名前が付けられたのかはわかりませんが、それらが最初と最後の要素を表しているからではありません。
kjfletch のリンクで説明されている方法で見る方が簡単ですinject() の内訳 、代わりに「結果」と「要素」という名前が付けられています。
inject() を使用する価値は、簡潔にする能力です。inject() でやりたいことは、 each() メソッドを呼び出して、はるかに長いブロックと追加の変数宣言を使用して実行することもできます。この質問と回答を参照して、その感覚をつかんでください。
Ruby でメソッドが何をするかを知りたい場合は、バンドルされているriツールを使用するか ("ri Enumerable.inject" と入力してドキュメントを検索できます)、Ruby-Docを検索できます。この場合、次のように表示されます。
ブロックをアキュムレータ値 (メモ) と各要素に順番に適用することにより、enum の要素を結合します。各ステップで、メモはブロックによって返された値に設定されます。最初の形式では、メモの初期値を指定できます。2 番目の形式は、コレクションの最初の要素を初期値として使用します (反復中にその要素をスキップします)。
# Sum some numbers
(5..10).inject {|sum, n| sum + n } #=> 45
# Multiply some numbers
(5..10).inject(1) {|product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo,word|
memo.length > word.length ? memo : word
end
longest #=> "sheep"
# find the length of the longest word
longest = %w{ cat sheep bear }.inject(0) do |memo,word|
memo >= word.length ? memo : word.length
end
longest #=> 5
完全を期すために:mは通常メモを意味します; kはキーを意味する場合があります(多くの場合、値を意味するvと組み合わせて使用します)。したがって、たとえば:
stuff.inject({}) { |m,(k,v)| m.merge(k.to_sym => v) }
また、次のように、アキュムレータにaを使用し、要素にeを使用する人もいます。
numbers.inject { |a,e| a+e }