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

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

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

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

3回答

649閲覧

Rubyでハッシュ値を特定の条件で変換したい

residenti

総合スコア11

Ruby

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2020/10/21 07:01

編集2020/10/22 01:56
{ :a => [ {:id => "1"}, {:id => "2"}, {:id => "5"}, # <= id が 2から5へと+3増えている。 {:id => "6"}, {:id => "9"}, # <= id が 6から9へと+3増えている。 {:id => "10"} ], :b => [ {:id => "1"}, {:id => "2"} ] }

Rubyで上のようなhashを、下のように変換したいです。

変換の条件は、配列に含まれるhash({:id=> "1"}など)のid値が一つ前のhashのidと比べて1より多く増加している場合に、自身が所属する配列のkey名(aなど)に_${num}を付けた値をkeyとして分離したいです。

{ :a => [ {:id=> "1"}, {:id=> "2"} ], :a_1 => [ {:id=> "5"}, {:id=> "6"} ], :a_2 => [ {:id=> "9"}, {:id=> "10"} ], :b => [ {:id=> "1"}, {:id=> "2"} ] }

どうぞよろしくお願いいたします。
(疑問などありましたら気兼ねなくご質問お願いしますm)

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

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

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

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

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

guest

回答3

0

ベストアンサー

chunk_while(偽になったところで分割)で。

Ruby

1require "pp" 2data = { 3 :a => [ 4 {:id => "1"}, 5 {:id => "2"}, 6 {:id => "5"}, # <= id が 2から5へと+3増えている。 7 {:id => "6"}, 8 {:id => "9"}, # <= id が 6から9へと+3増えている。 9 {:id => "10"} 10 ], 11 :b => [ 12 {:id => "1"}, 13 {:id => "2"} 14 ] 15} 16 17out = 18data.each_with_object({}) do |(k,v),o| 19 v.chunk_while do |x,y| 20 y[:id].to_i == x[:id].to_i + 1 21 end 22 .each_with_index do |x, i| 23 o[i==0 ? "#{k}" : "#{k}_#{i}"] = x 24 end 25end 26 27pp out 28#=> 29{"a"=>[{:id=>"1"}, {:id=>"2"}], 30 "a_1"=>[{:id=>"5"}, {:id=>"6"}], 31 "a_2"=>[{:id=>"9"}, {:id=>"10"}], 32 "b"=>[{:id=>"1"}, {:id=>"2"}]}

投稿2020/10/21 17:00

otn

総合スコア85901

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

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

residenti

2020/10/22 01:58

ご回答頂きありがとうございますm 参考にさせて頂きます。
guest

0

ruby

1input = { 2 :a => [ 3 {:id => "1"}, 4 {:id => "2"}, 5 {:id => "5"}, 6 {:id => "6"}, 7 {:id => "9"}, 8 {:id => "10"} 9 ], 10 :b => [ 11 {:id => "1"}, 12 {:id => "2"} 13 ] 14} 15 16pp input.map{|k, v| [k,v.chunk_while{|x, y| y[:id].to_i - x[:id].to_i == 1 }.to_a] } 17 .flat_map{|k, v| 18 count = -1 19 v.map{|l| 20 count += 1 21 [count == 0 ? "#{k}" : "#{k}_#{count}", l] 22 } 23 }.to_h

キーがシンボルから文字列に変化していますがそれでいいのでしょうか・・・

というかキーを動的に作成するとプログラムで処理しづらいので配列で対処したほうがよいかと
実際上記プログラムも分割までは1行で終わっていて残りはキーの処理です。

投稿2020/10/21 16:10

asm

総合スコア15149

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

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

residenti

2020/10/22 01:56

> キーがシンボルから文字列に変化していますがそれでいいのでしょうか・・・ こちら気付きませんでした。。。修正しました。 また、教えて頂いたコードで無事解決することができました。 ご回答頂きありがとうございましたm
guest

0

それっぽく動くコードを書いてみました

ruby

1def create_group_of_id(data) 2 ret = {} 3 4 data.keys.each do |key| 5 ids = data[key].map { |hash| hash[:id].to_i } 6 end_index = 0 7 key_count = 0 8 9 while ids[end_index] do 10 group = group_continuity_numbers(ids[end_index..-1]) 11 end_index = ids.index(group.last) 12 break if end_index.nil? 13 14 if key_count.zero? 15 ret.update(key => group.map { |id| {id: id.to_s} }) 16 else 17 ret.update("#{key}_#{key_count}".to_sym => group.map { |id| {id: id.to_s} }) 18 end 19 20 key_count += 1 21 end_index += 1 22 end 23 end 24 25 ret 26end 27 28def group_continuity_numbers(ids, ret = []) 29 return ret if ids.size.zero? 30 31 a, b, *ids = ids 32 33 return ret if a.nil? || b.nil? 34 return ret if (a - b).abs >= 2 35 36 group_continuity_numbers([b, ids].flatten, [ret, a, b].flatten.uniq) 37end 38 39data = 40 { 41 :a => [ 42 {:id => "1"}, 43 {:id => "2"}, 44 {:id => "5"}, # <= id が 2から5へと+3増えている。 45 {:id => "6"}, 46 {:id => "9"}, # <= id が 6から9へと+3増えている。 47 {:id => "10"} 48 ], 49 :b => [ 50 {:id => "1"}, 51 {:id => "2"}, 52 ] 53 } 54 55pp result = create_group_of_id(data) 56# => 57# { 58# :a=>[ 59# {:id=>"1"}, 60# {:id=>"2"} 61# ], 62# :a_1=>[ 63# {:id=>"5"}, 64# {:id=>"6"} 65# ], 66# :a_2=>[ 67# {:id=>"9"}, 68# {:id=>"10"} 69# ], 70# :b=>[ 71# {:id=>"1"}, 72# {:id=>"2"} 73# ] 74# }

他のデータを与えたり詳細なテストはしていないので、もしかしたら動かないパターンもあるかもしれません

なにか参考になれば幸いです

投稿2020/10/21 11:07

gouf

総合スコア2321

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

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

residenti

2020/10/22 01:52

そっそくご回答頂きありがとうございましたm こちら無事解決できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問