Rubyで配列の値を計算するのに便利なinjectメソッドをご存じでしょうか。Rubyには配列を対象とする便利なメソッドが幾つもありますが、使い方が限られているので使う機会が少ないメソッドをよく知らない、という方も多いでしょう。
そのような方は、ぜひinjectメソッドをマスターしてRubyらしいシンプルなプログラムを書けるようになりましょう。今回はそのような方のために、injectメソッドを利用した配列をシンプルに計算する方法を解説します。
Rubyのinjectとは
Rubyは、文法が簡単で覚えやすく、短くて読みやすいプログラムが書けるのが特徴です。特に配列(Array)やハッシュ(Hash)の要素に対する機能が充実しており、配列を使った繰り返し処理をシンプルに記述できます。
しかし全ての配列のメソッドを理解し、それを使い分けるのは大変です。今回紹介するRubyのinjectメソッドを使いこなしている方は少ないかもしれません。injectメソッドをうまく使えれば、eachメソッドなどで作るよりもシンプルに書くことが可能です。
まずは、injectメソッドの便利な点について解説します。
injectメソッドの機能とは
Rubyで配列の要素に対する繰り返し処理を作る際、いつもeachメソッドを使ってはいないでしょうか。Rubyには、配列(Array)とハッシュ(Hush)の要素に対するメソッドがたくさんあります。ぜひ、そのようなメソッドにも目を向けてください。
もし数字のみの配列が与えられて、その合計を計算するプログラムをRubyで作る場合、injectメソッドを使えば、eachメソッドを使うよりも読みやすいプログラムが書けます。
配列の合計を算出する例(eachメソッドを使用)
arr = [2, 3, 4, 5] result=0 arr.each {|val| result += val } p result
配列の合計を算出する例(injectメソッドを使用)
arr = [2, 3, 4, 5] result = arr.inject {|sum, val| sum + val } p result
injectの意味
injectは、元々英語の動詞で「注入する」「挟み込む」「注射する」といった意味です。なおinjectの語源はラテン語で、中に投げ入れる、という意味の言葉でした。
Rubyのinjectメソッドは、配列やハッシュの各要素を加工して、ブロック内で定義した1つの変数に次々に投げ入れている、といったイメージで考えると分かりやすいのではないでしょうか。
配列を使った繰り返し処理の特徴
Rubyに限らずプログラムで配列を使う目的は、繰り返し処理を利用したプログラムの簡略化です。さらにRubyには、シンプルに書ける便利なメソッドがたくさんあり、使い方によっては配列を利用した繰り返し処理をわずか1行で書けてしまいます。
そして、今回紹介するinjectメソッドもその1つです。もし、配列の要素を使って何かを計算したいなら、もちろんeachメソッドでも作れますが、ぜひinjectメソッドの利用を検討してください。
先ほどの例のように、injectメソッドでは計算結果を格納する変数をブロックの中に定義できます。このように、よりミスしにくいプログラムが書ける点もinjectメソッドを利用するメリットの1つです。
injectメソッドの基本
先ほど紹介したようにinjectメソッドは、ブロック内で配列の要素を演算してその演算結果を返すメソッドです。さらにブロックの書き方によっては、配列の要素を計算する複雑な処理も記述できます。
次からinjectメソッドの基本について解説します。
injectメソッドの文法
基本的なinjectメソッドの使い方は、ブロックの中に計算結果を格納する変数と要素を参照する変数とを指定し、それらの演算式を記述する方法です。
基本的なinjectメソッドの文法
(配列またはハッシュ).inject { | 計算結果を格納する変数, 変数と要素を参照する変数 |
…
計算結果を格納する変数と変数と要素を参照する変数を使った演算式
…
}
次にinjectメソッドの基本的な利用方法による例を紹介します。
配列に対するinjectメソッドの例
arr = [2, 3, 4, 5] out = arr.inject { |sum, val| sum + val } p out # 14が表示される
この例は、injectメソッドで配列arrの要素の合計を計算し、変数outに代入してその値を表示する例です。
injectメソッドで初期値を指定する
injectメソッドは、引数で初期値を指定しない場合、配列の要素の最初値として使い、次の要素から演算していきます。もし、ブロック内で要素を演算してその合計を求めるなら、引数で初期値を指定することをおすすめします。
初期値を指定し忘れた例
arr = [2, 3, 4, 5] out = arr.inject { |sum, val| sum += val * val } p out # 52が表示される
この例では、初期値を指定し忘れているので、初期値に2が代入され、3以降が計算された結果である52が表示されます。しかし、これは間違いです。
初期値0を指定した例
arr = [2, 3, 4, 5] out = arr.inject(0) { |sum, val| sum += val * val } p out # 54が表示される
この例では初期値に0が代入され、2以降で正しく演算された結果として54が表示されます
ハッシュでinjectメソッドを使うには
先ほど配列に対する例を使ってinjectメソッドを解説しましたが、injectはハッシュでも利用できます。しかし、ハッシュにはキーと値のペアでデータが格納されているので、配列と同じ使い方はできません。このようにinjectメソッドでハッシュを利用するには注意が必要です。
次からハッシュでinjectを使う方法について解説します。
もし配列と同じように使ったら
injectメソッドをハッシュに対して配列と同じように使用したらでしょうか。実は結果が全く違います。例えば、次のinjectメソッドの例を比べてみてください。
配列に対するinjectメソッドの例
arr = [1, 2, 3, 4] out = arr.inject { |sum, val| sum + val } p out # 10 が表示される
ハッシュに対するinjectメソッドの例
hash = {1=> 2, 3=> 4, 5=> 6, 7=> 8} out = hash.inject { |sum, val| sum + val } p out # [1, 2, 3, 4, 5, 6, 7, 8]
上記の例のように配列にinjectメソッドを使うと合計の14が表示されますが、ハッシュにinjectメソッドを使うとキーと値をばらばらにした新しい配列が作られます。このように、ハッシュの値の合計が算出される訳ではありません。
配列の要素がハッシュなら計算できる
先ほど紹介したようにハッシュにinjectを使ったとしても、要素の合計は算出されません。しかし、配列の要素がハッシュなら計算は可能です。
次にハッシュの特定のキーの要素の合計を算出する例を紹介します。
hash = [ {"No"=>1, "val"=>2} {"No"=>2, "val"=>3} {"No"=>3, "val"=>4} {"No"=>4, "val"=>5} ] out = hash.inject(0) { |sum, item| sum + item["val"] } p out # 14 が表示される
この例は、ハッシュを含む2次元配列hashに対してinjectメソッドを適用し、ブロック内でキー”val”の値の合計を算出し、それを表示します。
まとめ
これまで紹介したようにRubyのinjectメソッドを利用することで、配列やハッシュの要素の合計をシンプルに記述できます。そしてinjectメソッドは配列とハッシュで使えますが、その機能は違っているので注意してください。
Rubyには、配列を利用した繰り返し処理に使えるメソッドがたくさんあります。今回紹介したinjectメソッドも便利な機能なので、ぜひ、活用してください。