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

Ruby |配列内のハッシュを合体させる

More than 1 year has passed since last update.

配列内にあるハッシュを合体させ、かつ同じキーのバリューの値を合算させるということをやってみました。

Paizaをやっていたら今回のような状況になったので、備忘録として記事にしました。
もし参考になれば使ってみてください。

また、他にもいいやり方があるよー、ちょっと違いますよーって方がいればコメントしていただければと思います。

開発環境

Ruby 2.5.3

やりたかったこと

配列内にあるハッシュ達を合体させ、配列ではなく一つのハッシュにしたかった。
ただし、同じキーが重複している際は、バリューの数値を合算する
イメージ的には下のような感じです。

hash = [{a: 1},{b: 2},{b: 3},{c: 4}]

#何か処理をした結果
#=> {:a=>1, :b=>5, :c=>4}

きっとレベルの高い人は今回のような状況にならないのかもしれません。笑

完成形

ナンセンスなやり方かもしれませんが、一応求めていた結果になりました。

2つのハッシュをマージする - Ruby Tips!
上の記事を参考にして、injectメソッドと併用してみました。

hash = [{a: 1},{b: 2},{b: 3},{c: 4}]

merged_hash = hash.inject do |h1, h2|
  h1.merge(h2) do |key, oldval, newval|
    oldval + newval
  end
end

p merged_hash
#=> {:a=>1, :b=>5, :c=>4}

バリューを前後の2つの引数に分けて、取り出せるのは知りませんでした。

失敗例

自分でなんとかここまでは思いつき、うまくいくと思ったのですが、
一つのハッシュにはなるけど、合算ができず....

hash = [{a: 1},{b: 2},{b: 3},{c: 4}]

merged_hash = hash.inject do |h1, h2|
    h1.merge(h2) 
end

p merged_hash
#=> {:a=>1, :b=>3, :c=>4}
# :b=>5 になって欲しかった...

使用したメソッドの参考例

今回使用したメソッドの通常の使用例をまとめてみました。

mergeメソッド

Ruby 2.6.0 リファレンスマニュアル > Hash#merge

ハッシュ同士を合体してくれるメソッド
合体する際に同じキーがある場合は、バリューの数値を合算してくれる。

h1 = {a: 1, b: 2, c: 3, d: 4}
h2 = {e: 5, f: 6}
h3 = {a: 10, b: 20}

p h1.merge(h2)
# => {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}

p h1.merge(h3)
# => {a: 11, b: 22, c: 3, d: 4}
# 値が合算される

injectメソッド

Ruby 2.6.0 リファレンスマニュアル > Enumerable#inject

配列を繰り返し処理する際に、前の要素と今の要素を条件に沿って処理してくれる。
今回の例は、足し算にしているので合計を算出してくれます。

numbers = [1,2,3,4,5]

numbers.inject do |n, m|
    n + m
end

# or

numbers.inject(&:+)

# => 21

Ruby 2.6 以降の書き方

色々とコメントをいただき、正しい情報を追記させていただきました。

Class: Hash (Ruby 2.6.1)
Ruby 2.6からは以下のような書き方も可能になったみたいです。
injectを使わなくてもマージかつ合算できるのは便利。
逆に言えば、injectmergeの組み合わせが定番だったからこそ、こうなったのかな?と。

hash = [{a: 1}, {b: 2}, {b: 3}, {c: 4}]

{}.merge(*hash) { |_key, v1, v2| v1 + v2 }
#=> {:a=>1, :b=>5, :c=>4}

{}.merge(*hash)
#=> {:a=>1, :b=>3, :c=>4}

他にもコメント欄に別の書き方が記載されています。参考にしてください。

さいごに

そもそもブロック内にまた別のブロックを作ることって実際ありなのかな?って一瞬思いましたが、他に何も思いつきませんでした。
もし、他にやり方があればぜひ教えていただきたいです。

読んでいただきありがとうございました!

ynoc
クラウドを活用したシステムインテグレーションを提供しています
http://www.ynoc.co.jp/
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
ユーザーは見つかりませんでした