这个问题的this question倒数。转换嵌套散列成扁平散列
给定一个嵌套的哈希像
{
:a => {
:b => {:c => 1, :d => 2},
:e => 3,
},
:f => 4,
}
是什么把它转换成一个平坦的哈希像
{
[:a, :b, :c] => 1,
[:a, :b, :d] => 2,
[:a, :e] => 3,
[:f] => 4,
}
这个问题的this question倒数。转换嵌套散列成扁平散列
给定一个嵌套的哈希像
{
:a => {
:b => {:c => 1, :d => 2},
:e => 3,
},
:f => 4,
}
是什么把它转换成一个平坦的哈希像
{
[:a, :b, :c] => 1,
[:a, :b, :d] => 2,
[:a, :e] => 3,
[:f] => 4,
}
的另一种方法:
def flat_hash(h,f=[],g={})
return g.update({ f=>h }) unless h.is_a? Hash
h.each { |k,r| flat_hash(r,f+[k],g) }
g
end
h = { :a => { :b => { :c => 1,
:d => 2 },
:e => 3 },
:f => 4 }
flat_hash(h) #=> {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}
最好的办法,这不是一个试图给你最好办法做到这一点,但它是一种方法:P
def flatten(hash)
return {[] => hash} if !hash.is_a?(Hash)
map = {}
hash.each_pair do |key1, value1|
flatten(value1).each_pair do |key2, value2|
map[[key1] + key2] = value2
end
end
return map
end
它适用于您的例如,产生这样的结果:
{[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}
它可能不会产生您期望的结果,如果有空散列。
非常相似,Adiel Mittmann的解决方案
def flat_hash(h, k = [])
new_hash = {}
h.each_pair do |key, val|
if val.is_a?(Hash)
new_hash.merge!(flat_hash(val, k + [key]))
else
new_hash[k + [key]] = val
end
end
new_hash
end
编辑:重构高雅。应该几乎一样快。
def flat_hash(hash, k = [])
return {k => hash} unless hash.is_a?(Hash)
hash.inject({}){ |h, v| h.merge! flat_hash(v[-1], k + [v[0]]) }
end
我尝试:
def flatten_hash(h)
return { [] => h } unless h.is_a?(Hash)
Hash[h.map { |a,v1| flatten_hash(v1).map { |b,v2| [[a] + b, v2] } }.flatten(1)]
end
很抱歉的坏变量的名称,必须适应它在同一行。
的功能的方法(参见history一种替代的实施方式):
def recursive_flatten(hash)
hash.flat_map do |key, value|
if value.is_a?(Hash)
recursive_flatten(value).map { |ks, v| [[key] + ks, v] }
else
[[[key], value]]
end
end.to_h
end
通过@卡里-swoveland方式的启发,但在哈希类:
class Hash
def deep_flatten(previous_key=[])
flat_hash = {}
self.each do |key, value|
next_key = previous_key+[key]
flat_hash.update(value.is_a?(Hash) ? value.deep_flatten(next_key) : {next_key=>value})
end
return flat_hash
end
end
h = { :a => { :b => { :c => 1, :d => 2 }, :e => 3 }, :f => 4 }
h.deep_flatten #=> {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}
声明性溶液使用DeepEnumerable:
require 'deep_enumerable'
h = { :a => { :b => { :c => 1, :d => 2 }, :e => 3 }, :f => 4 }
h.deep_each.map do |k, v|
[DeepEnumerable.deep_key_to_array(k), v]
end.to_h
,或者为那些喜欢谁点自由式
h.deep_each.to_h.shallow_map_keys(&DeepEnumerable.method(:deep_key_to_array))
阵列支持/可读的名称/速度/字符串化的结果键没有更新
def flat_hash(input, base = nil, all = {})
if input.is_a?(Array)
input = input.each_with_index.to_a.each(&:reverse!)
end
if input.is_a?(Hash) || input.is_a?(Array)
input.each do |k, v|
flat_hash(v, base ? "#{base}.#{k}" : k, all)
end
else
all[base] = input
end
all
end
所以你想要一个键数组以便产生一个值? – Linuxios 2012-03-10 16:59:06