はじめに
配列の各要素を加算する際によく使われる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