ruby初心者です。階層の深いhashの作り方
解決済
回答 2
投稿
- 評価
- クリップ 1
- VIEW 1,644
いま、深い階層を作成しようとしています。
しかし、途中で行き詰まってしまいどうしていいかわからなくなってしましました。
h_symptom=Hash.new
symptom=Array.new
cause1=Array.new
cause2=Array.new
a_line.each{|dset|
if dset[0]==3 then
h_symptom[dset[1]]=Hash.new
symptom=dset[1]
elsif dset[0]==6 then
h_symptom[symptom][dset[1]]=Hash.new
cause1=dset[1]
elsif dset[0]==9 then
h_symptom[symptom][cause1][dset[1]]=Hash.new
cause2=dset[1]
elsif dset[0]==12 then
h_symptom[symptom][cause1][cause2] = dset[1]
end
}
dset[0]には3の倍数が入っており、さらに深い階層にも対応させたいです。
3,a
6,b
9,c
12,d
15,e
18,f
3、あ
6,い
a_lineはこんな感じになっています。
3から次の3までを階層にしたい場合、どうしたら簡略的に書くことが出来ますでしょうか?
よろしくお願いします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
こういう書き方は,「どこまでがキーでどこからが値なのか」が不明瞭になるので(競技プログラミングでこういう問題が用意されている場合を除き)設計ミスです.葉要素の値は空ハッシュにしてしまうほうがいいと思います.
entries = [
[3, :a],
[6, :b],
[9, :c],
[12, :d],
[15, :e],
[18, :f],
[3, :あ],
[6, :い],
]
root = {}
entries.inject(root) do |node, entry|
node = root if entry[0] == 3
node[entry[1]] = {} if node[entry[1]].nil?
node[entry[1]]
end
p root
# {:a=>{:b=>{:c=>{:d=>{:e=>{:f=>{}}}}}}, :あ=>{:い=>{}}}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
次の機能を実装してみました。
- ネストレベルが0番でないものが複数並ぶ場合を処理できるようにする。
- 入力データの数字が 3 9 と飛んでいたらエラーにする。
- ネストしたハッシュを入力データの形式で表示する。
aa.rb
require 'awesome_print' # gem install awesome_print
# 質問文にあったデータ例
data0 = <<'EOS'
3,a
6,b
9,c
12,d
15,e
18,f
3,あ
6,い
EOS
# 追加したデータ例
data1 = <<'EOS'
3,a
6,b
9,c
3,あ
6,い
9,1
9,2
6,う
9,10
9,20
EOS
# 不正なデータ例
dataX = <<'EOS'
3,a
9,c
EOS
# [nest, key] の組に配列データからネストしたハッシュを生成する
def make_hash(lines)
ans = {}
keys = []
lines.each do |line|
pos = line[0] / 3 - 1
fail "Bad data: #{line}" if pos > keys.length
keys = (pos == 0) ? [] : keys[0..(pos - 1)]
keys << line[1]
keys.inject(h = ans) do |h, key|
h[key] = {} unless h[key]
h[key]
end
end
ans
end
def print_keys(hash, nest = 0)
hash.each do |key, val|
puts "#{(nest + 1) * 3} #{key}"
print_keys(val, nest + 1) unless val.empty?
end
end
a_lines = data0.lines.map do |line|
x = line.chop.split(',')
[x[0].to_i, x[1..-1].join(' ')]
end
hash = make_hash(a_lines)
ap hash
p hash
print_keys(hash)
puts
a_lines = data1.lines.map do |line|
x = line.chop.split(',')
[x[0].to_i, x[1..-1].join(' ')]
end
hash = make_hash(a_lines)
ap hash
print_keys(hash)
puts
a_lines = dataX.lines.map do |line|
x = line.chop.split(',')
[x[0].to_i, x[1..-1].join(' ')]
end
hash = make_hash(a_lines)
# ap hash
実行結果
$ ruby aa.rb
{
"a" => {
"b" => {
"c" => {
"d" => {
"e" => {
"f" => {}
}
}
}
}
},
"あ" => {
"い" => {}
}
}
{"a"=>{"b"=>{"c"=>{"d"=>{"e"=>{"f"=>{}}}}}}, "あ"=>{"い"=>{}}}
3 a
6 b
9 c
12 d
15 e
18 f
3 あ
6 い
{
"a" => {
"b" => {
"c" => {}
}
},
"あ" => {
"い" => {
"1" => {},
"2" => {}
},
"う" => {
"10" => {},
"20" => {}
}
}
}
3 a
6 b
9 c
3 あ
6 い
9 1
9 2
6 う
9 10
9 20
aa.rb:41:in `block in make_hash': Bad data: [9, "c"] (RuntimeError)
from aa.rb:39:in `each'
from aa.rb:39:in `make_hash'
from aa.rb:83:in `<main>'
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
mpyw
2016/04/09 08:05
本題とは無関係ですが
symptom=Array.new
cause1=Array.new
cause2=Array.new
これいらないです.ここで作ったインスタンスが結局
symptom=dset[1]
こういった処理に全て上書きされています.