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

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

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

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

Q&A

解決済

3回答

3185閲覧

ネストしたハッシュから新たなハッシュを作成したい

Takkiii

総合スコア14

Ruby

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

0グッド

0クリップ

投稿2015/08/06 02:58

こんにちは、今開発で少し悩んでいるところがあり質問させて頂きます。
まず見て頂きたいのが以下のコードです。

ruby

1hash = {"4"=>{"site_id"=>1}, "7"=>{"site_id"=>1}, "10"=>{"site_id"=>2}}

今回行いたい操作は
・site_idの値どうしを比較して同じものが存在した場合( 子ハッシュ部分の操作 )
・それらのハッシュに対応するkeyどうしを比較し( 親ハッシュ部分の操作 )
・keyの値が大きいものを削除する
といった感じです。
最終的にこうしたいです。

ruby

1hash = {"4"=>{"site_id"=>1}, "10"=>{"site_id"=>2}}

ランキング機能のようなものをrailsで実装したく、
最終的にはkeyとsite_idの値をインスタンス変数などに格納できればと考えています。
必要に応じて配列化してしまっても構いません。
どうぞよろしくお願いします!

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんな感じでどうでしょうか?

Ruby

1hash = {"4"=>{"site_id"=>1}, "7"=>{"site_id"=>1}, "10"=>{"site_id"=>2}} 2p hash 3 .each_pair # pair配列のEnumeratorにする 4 .group_by{|x|x[1]["site_id"]} # "side_id"でグループ化 5 .each_value # 必要なのはvalueだけなので、valueだけのEnumeratorにする 6 .map{|v|v.min_by{|x|x[0]}} # キーであるx[0]が最小になるのを取り出す 7 .to_h # 最後にHashに戻す 8#=> {"4"=>{"site_id"=>1}, "10"=>{"site_id"=>2}}

投稿2015/08/06 09:41

raccy

総合スコア21735

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

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

otn

2015/08/06 10:34

group_byは使用語彙になかったです。勉強になりました。
guest

0

みなさんありがとうございます。

あれから1時間くらい試行錯誤していたら何とか自分でもできました。
一応、コードを紹介しますね。

ruby

1def get_uniq_data(hash) 2 # hashのvalueのみの配列から、site_idに対応するvalueのみの配列をmapで作る 3 site_id = hash.values.map { |item| 4 item["site_id"] 5 } 6 # 配列site_idの中からユニークでないidのみを抜き出す 7 ununiq_id = site_id.uniq.select{|i| site_id.index(i) != site_id.rindex(i)}[0] 8 # site_idがununiq_idであるものに対応するkeyのみの配列を作る 9 ununiq_keys = hash.map { |item| 10 item[0].to_i if item[1]["site_id"] == ununiq_id 11 }.compact 12 # sortしたものの最初の要素( 値が最も小さいもの )を抜き出す 13 uniq_key = ununiq_keys.sort.first 14 # site_idがユニークでない、またはkeyがユニークであるもののみをハッシュに残し他は削除する 15 hash.keep_if { |key, value| 16 value["site_id"] != ununiq_id || key.to_i == uniq_key 17 } 18 end

といった感じでいくつかステップを踏んで実装しました。
やや冗長だったりrubyの仕組みをうまく活用できていない部分等あるかと思うので簡単にレビュー等あればありがたいです。

投稿2015/08/07 05:43

Takkiii

総合スコア14

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

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

0

こんな感じでしょうか。

Ruby

1hash = {"4"=>{"site_id"=>1}, "7"=>{"site_id"=>1}, "10"=>{"site_id"=>2}} 2 3keep = hash.sort_by{|k,v| [v["site_id"],k]}.each_with_object({}){|(k,v),x| x[v["site_id"]]||=k}.values 4 5p hash.select{|k,v| keep.include?(k)}

"4" "7" "10" を「親のキー」と呼ぶことにします。
・ハッシュを、site_idの値を第一キー、「親のキー」を第二キーとしてソート
・新たにハッシュをつくる。キーはsite_idで、キーが存在しなければ「親のキー」を値としてセット
→これでsite_idごとに最小の「親のキー」が得られる
・今作ったハッシュの値一覧が、残すべき「親のキー」

投稿2015/08/06 06:41

編集2015/08/06 07:38
otn

総合スコア84499

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

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

otn

2015/08/06 10:41

raccyさんの回答にコメントしましたが、group_byは勉強になりました。 比較すると、私の方のメリットとしては、元のhashをselectするので、順序が保たれるというくらいですね。多分順序を保つ必要は無さそうなので、raccyさんの方がシンプルで良いかと
Takkiii

2015/08/07 04:47

なるほど、自分でもロジック組めたのですが参考になる点が多く勉強になりました。 どうもありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問