Help us understand the problem. What is going on with this article?

injectとeach_with_objectって何が違うのさ?

More than 5 years have passed since last update.

injecteach_with_objectの違いが分からない。
どちらもEnumerableなオブジェクトの要素を使って何かしらのオブジェクトを得る。

でもやっぱり違いがあったのでメモ。

イメージで説明

  • injectは、各要素が力を合わせて一つのオブジェクトを作る
  • each_with_objectは、ターゲットとなるオブジェクトに対して、各要素を作用させる

挙動で説明

配列の各要素を2乗する処理を書く。表面上は同じ挙動をする。
でもdoの後のresultは、同じresultでも意味合いが違っていて、

  • injectの場合はresultにはブロック内で最後に評価した値が入る
  • each_with_objectの場合は、resultは常にeach_with_objectの引数として渡されたオブジェクトを指す
hoge.rb
# inject
[1, 2, 3].inject [] do |result, i|
  result << i*i
end

# each_with_object
[1, 2, 3].each_with_object [] do |i, result|
  result << i*i
end

injectを使いたい場合の例

たとえば配列の和を求める場合

hoge.rb
sum = [1, 2, 3].inject 0 do |s, i|
  s + i
end

(この場合はsum = [ 1, 2, 3].inject :+でいいけど敢えてこの形で。)

ここでeach_with_objectを使おうとしてしまうと、

hoge.rb
sum = [ 1, 2, 3].each_with_object 0 do |i, s|
  s += i
end

とすればよさげだけど、sは破壊的に変更できない0(Fixnum)を指しているので、
sumに入るのは0となってしまう。

each_with_objectを使いたい場合の例

たとえば[["Alice", 50], ["Bob", 40], ["Charlie", 70]]から、{"Alice" => 50, "Bob" => 40, "Charlie" => 70}を得たい場合、

hoge.rb
ret = [["Alice", 50], ["Bob", 40], ["Charlie", 70]].each_with_object({}) do |(key, value), hash|
  hash[key] = value
end

こんな感じでかける。

ここでinjectを使おうとすると、できないわけではないけど、
作成中のハッシュをブロックの最後に評価しないといけないので1行余分に必要になる。

hoge.rb
ret = [["Alice", 50], ["Bob", 40], ["Charlie", 70]].inject({}) do |hash, (key, value)|
  hash[key] = value
  hash    # ブロックの最後の評価を作成中のハッシュにしないといけない
end

参考:
プログラミングは素晴らしい - [プログラミング] each、each_with_object、inject、map

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした