次の機能を実装してみました。
- ネストレベルが0番でないものが複数並ぶ場合を処理できるようにする。
- 入力データの数字が 3 9 と飛んでいたらエラーにする。
- ネストしたハッシュを入力データの形式で表示する。
aa.rb
ruby
1require 'awesome_print' # gem install awesome_print
2
3# 質問文にあったデータ例
4data0 = <<'EOS'
53,a
66,b
79,c
812,d
915,e
1018,f
113,あ
126,い
13EOS
14
15# 追加したデータ例
16data1 = <<'EOS'
173,a
186,b
199,c
203,あ
216,い
229,1
239,2
246,う
259,10
269,20
27EOS
28
29# 不正なデータ例
30dataX = <<'EOS'
313,a
329,c
33EOS
34
35# [nest, key] の組に配列データからネストしたハッシュを生成する
36def make_hash(lines)
37 ans = {}
38 keys = []
39 lines.each do |line|
40 pos = line[0] / 3 - 1
41 fail "Bad data: #{line}" if pos > keys.length
42
43 keys = (pos == 0) ? [] : keys[0..(pos - 1)]
44 keys << line[1]
45 keys.inject(h = ans) do |h, key|
46 h[key] = {} unless h[key]
47 h[key]
48 end
49 end
50 ans
51end
52
53def print_keys(hash, nest = 0)
54 hash.each do |key, val|
55 puts "#{(nest + 1) * 3} #{key}"
56 print_keys(val, nest + 1) unless val.empty?
57 end
58end
59
60a_lines = data0.lines.map do |line|
61 x = line.chop.split(',')
62 [x[0].to_i, x[1..-1].join(' ')]
63end
64hash = make_hash(a_lines)
65ap hash
66p hash
67print_keys(hash)
68puts
69
70a_lines = data1.lines.map do |line|
71 x = line.chop.split(',')
72 [x[0].to_i, x[1..-1].join(' ')]
73end
74hash = make_hash(a_lines)
75ap hash
76print_keys(hash)
77puts
78
79a_lines = dataX.lines.map do |line|
80 x = line.chop.split(',')
81 [x[0].to_i, x[1..-1].join(' ')]
82end
83hash = make_hash(a_lines)
84# 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>'