我有一个源哈希:
a = {'1' => 'A',
'2' => 'B',
'3' => 'C',
'4' => { '5' => 'D', '6' => 'E', '7' => { '8' => 'F', '9' => 'G' }},
'10' => {'11' => 'H'}}
我需要构造一个方法来使它成为一个平面哈希(单个哈希)。结果应如下所示:
a = {'1' => 'A', '2' => 'B', '3' => 'C', '5' => 'D', '6' => 'E', '8' => 'F', '9' => 'G', '11' => 'H'}
我尝试使用merge
,deep_merge
,each_with_object
和recursion
,但他们没有给出正确的结果。
感谢任何帮助。
答案 0 :(得分:2)
a = {'1' => 'A',
'2' => 'B',
'3' => 'C',
'4' => { '5' => 'D', '6' => 'E', '7' => { '8' => 'F', '9' => 'G' }},
'10' => {'11' => 'H'}}
# recursive detect value is Hash or not
compact_hash = ->(hh, h0={}) {
hh.reduce(h0) do |h, (k, v)|
if v.is_a? Hash
compact_hash[v, h]
else
h[k] = v
h
end
end
}
puts compact_hash[a]
非常感谢@cary,我知道如何在没有;
的情况下执行单行并删除h
。
compact_hash = ->(hh, h0={}) {
hh.each_with_object(h0) { |(k, v), h | v.is_a?(Hash) ? compact_hash[v, h] : h[k] = v }
}
答案 1 :(得分:1)
h = { '1' => 'A', '2' => 'B', '3' => 'C',
'4' => { '5' => 'D', '6' => 'E', '7' => { '8' => 'F', '9' => 'G' } },
'10' => { '11' => 'H'} }
hh = h.dup
loop do
g = hh.select { |_,v| v.is_a? Hash }
break hh if g.empty?
g.keys.each { |k| hh.delete(k) }
g.values.each { |f| hh.update(f) }
end
#=> {"1"=>"A", "2"=>"B", "3"=>"C", "5"=>"D", "6"=>"E", "11"=>"H", "8"=>"F", "9"=>"G"}
这不会改变h
:
h #=> { "1"=>"A", "2"=>"B", "3"=>"C",
# "4"=>{"5"=>"D", "6"=>"E", "7"=>{"8"=>"F", "9"=>"G"}},
# "10"=>{"11"=>"H"}}
倒数第三行可以替换为以下内容。
g_keys = g.keys
hh.delete_if { |k| g_keys.include?(k) }
我不知道效率会更高。
答案 2 :(得分:0)
a = {'1' => 'A',
'2' => 'B',
'3' => 'C',
'4' => { '5' => 'D', '6' => 'E', '7' => { '8' => 'F', '9' => 'G' }},
'10' => {'11' => 'H'}}
def flatten_hash(hash)
hash.each_pair.reduce({}) do |h, (k, v)|
v.is_a?(Hash) ? h.merge(flatten_hash(v)) : h.merge(k => v)
end
end
# pry(main)> flatten_hash(a)
#=> {"1"=>"A", "2"=>"B", "3"=>"C", "5"=>"D", "6"=>"E", "8"=>"F", "9"=>"G", "11"=>"H"}