Just do IT

思うは招く

Ruby each_with_object の挙動やサンプル

Ruby には each_with_objectメソッドがある。

docs.ruby-lang.org

名前のとおり、eachメソッドを使えて、空の配列やハッシュなどを引数に渡してそれをオブジェクトとして処理できる。最終的には引数に渡した配列やハッシュを返す。

配列の場合

each_with_object([])と引数に空配列を渡すことで、|num, ary|のようにブロックの第二引数に空配列を渡すことができる。

result = (1..5).each_with_object([]) do |num, ary|
    p num
    p ary
end
p result

1
[]
2
[]
3
[]
4
[]
5
[]

渡した空配列に、ブロックの第一引数の要素を<<していく。

result = (1..5).each_with_object([]) do |num, ary|
    p ary << num * 5
end
p result =
[5]
[5, 10]
[5, 10, 15]
[5, 10, 15, 20]
[5, 10, 15, 20, 25]
=> [5, 10, 15, 20, 25]

numに5をかけた数値を[]に代入している。

ハッシュの場合

each_with_object({})のように、引数にハッシュを渡すこともできる。

hash = { a: "テイタム", b: "ブラウン", c: "ウォーカー" }
result = hash.each_with_object({}) do |item, new_hash|
  p item
  p new_hash
end
p result

[:a, "テイタム"]
{}
[:b, "ブラウン"]
{}
[:c, "ウォーカー"]
{}

この場合、ブロックの第一引数にはハッシュの要素が配列の形で入っている。

ハッシュのkeyやvalueを使う場合には、ブロックの第一引数に(key, value)と書くことでどちらも扱うことができる。

hash = { a: "テイタム", b: "ブラウン", c: "ウォーカー" }
result = hash.each_with_object({}) do |(key, value), new_hash|
  p key
  p value
  p new_hash
end
p result
:a
"テイタム"
{}
:b
"ブラウン"
{}
:c
"ウォーカー"
{}

each_with_object({})で引数に入れているハッシュを使ってみると、こうなる。

result = hash.each_with_object({}) do |(key, value), new_hash|
  new_hash["#{key}"] = "#{value}だよん"
end
p result

{"a"=>"テイタムだよん", "b"=>"ブラウンだよん", "c"=>"ウォーカーだよん"}

ここでは、new_hashの各keyとして、もともとはシンボルだったkeyを文字列にして、その要素にvalueを代入している。

もともとシンボルだったkeyをそのままシンボルとして使うなら、こうなる。

hash = { a: "テイタム", b: "ブラウン", c: "ウォーカー" }
result = hash.each_with_object({}) do |(key, value), new_hash|
  new_hash[key] = "#{value}だよん"
end
p result

{:a=>"テイタムだよん", :b=>"ブラウンだよん", :c=>"ウォーカーだよん"}

配列とハッシュの場合

レシーバに配列、引数にハッシュを渡すこともできる。

ary = [1, 2, 3]
hash = ary.each_with_object({}) do |value, new_hash|
  new_hash[value] = "hoge"
end
p hash

{1=>"hoge", 2=>"hoge", 3=>"hoge"}