はじめに
配列の各要素を加算する際によく使われるinjectメソッド。
その中でも、inject(:+)によるリファクタリングと、:+の意味について解説します。
この記事が役に立つ方
- もっとスッキリコードを書きたい
- Ruby初心者
この記事のメリット
-
inject(:+)の意味がわかる - 配列の各要素の演算をする際の引き出しが増える
環境
- Ruby 2.6.3
injectメソッドとは?
リストのたたみこみ演算を行ってくれるメソッド。
詳細はRubyリファレンスマニュアルをご確認下さい。
instance method Enumerable#inject (Ruby 2.6.0)
基本構文
inject(init){ |result, item| result + item }
# or
inject(symbol)
2通りあります。
inject(:+)は後者です。
よく使われる用法
主に配列に対して、要素の合計を算出したい場合に用いられます。
一番よく見る記法は、タイトルにもあるinject(:+)です。
前提
整数のみの配列arrayを以下のように定義します。
こちらのarrayの総和resultを求める記法を比較します。
array = [1, 4, 6, 34, 235]
each
result = 0
array.each{ |i| result += i }
p result
=> 280
3行。無駄に長い。
inject(通常の記法)
result = array.inject{ |sum, i| sum + i}
=> 280
eachと比べて2行削減出来ました。
inject(:+)(シンボルを用いた記法)
result = array.inject(:+)
=> 280
スッキリ!
逆に何が起こっているのか理解しづらいので、後ほど説明します。
sum
result = array.sum
=> 280
最高にシンプル!
:+の意味
inject(:+)の:+は、Symbolオブジェクトです。
自分は最初何をやっているのか全然理解出来なかったので、以下でも試してみました。
きっとこれで**「なるほどね!」**と理解出来ると思います。
演算子で配列の各要素をつないでくれるイメージですね。
:*の場合
result = array.inject(:*)
=> 191760
# 1 * 4 * 6 * 34 * 235 = 191760
:-の場合
result = array.inject(:-)
=> -278
# 1 - 4 - 6 - 34 - 235 = -278
各記法ごとの処理速度
こちらの2つの記事で詳細が記載されていました。
具体的でわかりやすい。
Rubyいろんな処理のベンチマーク選手権 - Qiita
Rubyで配列の要素を合計するベストな方法 - Qiita
sumが爆速!
inject(:+)はその次なんですね。参考になります。
【余談】reduceとの違いは?
Rubyではinjectメソッドとreduceメソッドは同じ働きをします。
英単語の意味は、
inject 「注射する・注入する」
reduce 「減らす・減少させる」
このせいで、最初なんで一緒なの?とすごく疑問だったのですが、以下記事の**「reduceとinjectの発想の違い」**という箇所で解説されていました。
図まで用意されていて超わかりやすかったです。
気になった方は是非ご確認下さい。
reduce は「あるルールに従ってデータ構造内の要素数を縮小していき、最後に残った値を返す」という発想になります。
inject は「値をプールしておくバケツを用意しておき、データ構造内の全ての要素をひとつずつ、ある処理にしたがってバケツに注入していく」という発想になります。
map と collect、reduce と inject ―― 名前の違いに見る発想の違い
おわりに
(:+)ってクマに見えませんか?笑![]()
参考にさせて頂いたサイト(いつもありがとうございます)
instance method Enumerable#inject (Ruby 2.6.0)
map と collect、reduce と inject ―― 名前の違いに見る発想の違い
Rubyいろんな処理のベンチマーク選手権 - Qiita
Rubyで配列の要素を合計するベストな方法 - Qiita