質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

マージ

複数のデータベースやファイル、プログラムなどを決まった手順や規則に従って一つに結合すること。

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1658閲覧

Ruby 複雑なhashをmergeする方法を知りたい

onoderamasuo

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

マージ

複数のデータベースやファイル、プログラムなどを決まった手順や規則に従って一つに結合すること。

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2020/06/12 09:10

前提・実現したいこと

配列を含むhashをmergeし、出力結果のようになるにはどのようなコードになるでしょうか。
解答お願いいたします。

コード

Ruby

1obj1 = { a: 3, b: { c: 1, d: [ 6, 3 ], e: 2 } } 2obj2 = { a: 1, b: { c: 2, d: [ 2, 0, 4 ], f: 1 } } 3obj3 = { b: { d: [ 1 ] } } 4 5def merge(*object) 6 #ここコードを知りたい 7end

望ましい出力結果

{ a: 1, b: { c: 2, d: [6, 2, 1, 3, 0, 4], e: 2, f: 1 } }

補足情報

*ライブラリは無使用でお願いします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asm

2020/06/12 10:27

配列を結合したときの順番が d: [6, 3, 2, 0, 4, 1] ならば割と簡単なのですが、並び替えは可能でしょうか?
onoderamasuo

2020/06/12 10:39

結合後の並び替えは可能です。
otn

2020/06/12 11:46

えー、Arrayは順不同だったの? 順番が肝かと思ったのに。
guest

回答2

0

ベストアンサー

Hash#mergeにはブロックを渡せますので

ruby

1def merge(*object) 2 x = object.shift 3 func = proc do |key, old_val, new_val| 4 case old_val 5 when Hash 6 old_val.merge(new_val, &func) 7 when Array 8 old_val + new_val 9 else 10 new_val 11 end 12 end 13 x.merge(*object, &func) 14end 15 16p merge(obj1, obj2, obj3) 17# => {:a=>1, :b=>{:c=>2, :d=>[6, 3, 2, 0, 4, 1], :e=>2, :f=>1}}

が可能です。

投稿2020/06/12 11:14

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

onoderamasuo

2020/06/12 11:38

ありがとうございます。 とても勉強になりました。
guest

0

Ruby

1obj1 = { a: 3, b: { c: 1, d: [ 6, 3 ], e: 2 } } 2obj2 = { a: 1, b: { c: 2, d: [ 2, 0, 4 ], f: 1 } } 3obj3 = { b: { d: [ 1 ] } } 4 5def merge(*object) 6 {}.merge(*object) do |k, v1, v2| 7 if Array===v1 and Array===v2 8 if v1.size < v2.size 9 v1 << [nil] * (v2.size-v1.size) 10 end 11 v1.zip(v2).flatten.compact 12 elsif Hash===v1 and Hash===v2 13 merge(v1,v2) 14 else 15 v2 16 end 17 end 18end 19 20p merge(obj1, obj2, obj3) 21#=> {:a=>1, :b=>{:c=>2, :d=>[6, 1, 2, 3, 0, 4], :e=>2, :f=>1}}

で良いかと思ったのですが、結果が、

plain

1{:a=>1, :b=>{:c=>2, :d=>[6, 1, 2, 3, 0, 4], :e=>2, :f=>1}}

になります。
:d=>[6, 2, 1, 3, 0, 4]にするためには、Arrayのマージをハッシュのマージが全部終わってから行う必要があるので、かなり面倒ですが、興味がわいたのでやってみました。

Ruby

1obj1 = { a: 3, b: { c: 1, d: [ 6, 3 ], e: 2 } } 2obj2 = { a: 1, b: { c: 2, d: [ 2, 0, 4 ], f: 1 } } 3obj3 = { b: { d: [ 1 ] } } 4 5class Foo 6 def initialize(x) 7 @x = [x] 8 end 9 def add(x) 10 @x << x 11 self 12 end 13 def merge 14 l = @x.map(&:size).max 15 ([nil]*l).zip(*@x).flatten.compact 16 end 17end 18 19def merge_sub(*object) 20 {}.merge(*object) do |k, v1, v2| 21 if Array===v1 and Array===v2 22 Foo.new(v1).add(v2) 23 elsif Foo===v1 and Array===v2 24 v1.add(v2) 25 elsif Hash===v1 and Hash===v2 26 merge_sub(v1,v2) 27 else 28 v2 29 end 30 end 31end 32 33def transform_sub(hash) 34 hash.transform_values do |v| 35 case v 36 when Foo 37 v.merge 38 when Hash 39 transform_sub(v) 40 else 41 v 42 end 43 end 44end 45 46def merge(*object) 47 transform_sub(merge_sub(*object)) 48end 49 50p merge(obj1, obj2, obj3) 51#=> {:a=>1, :b=>{:c=>2, :d=>[6, 2, 1, 3, 0, 4], :e=>2, :f=>1}}

投稿2020/06/12 11:44

otn

総合スコア84507

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

onoderamasuo

2020/06/12 12:32

興味を持っていただきありがとうございます。 とても勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問