将嵌套哈希转换为平面哈希

saw*_*awa 26 ruby hash

这个问题与这个问题相反.

给出一个嵌套的哈希值

{
    :a => {
       :b => {:c => 1, :d => 2},
       :e => 3,
    },
    :f => 4,
}
Run Code Online (Sandbox Code Playgroud)

什么是将其转换为平坦哈希的最佳方式

{
    [:a, :b, :c] => 1,
    [:a, :b, :d] => 2,
    [:a, :e] => 3,
    [:f] => 4,
}
Run Code Online (Sandbox Code Playgroud)

Car*_*and 18

其他方式:

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}
Run Code Online (Sandbox Code Playgroud)


Kyl*_*yle 16

与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
Run Code Online (Sandbox Code Playgroud)

编辑:改造优雅.应该几乎一样快.

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
Run Code Online (Sandbox Code Playgroud)


Nik*_* B. 8

我的尝试:

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
Run Code Online (Sandbox Code Playgroud)

对不起变量名称抱歉,必须在一行中插入.


Adi*_*ann 5

这不是试图给你最好的方法,但它是一种方式: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
Run Code Online (Sandbox Code Playgroud)

它适用于您的示例,产生以下结果:

{[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}
Run Code Online (Sandbox Code Playgroud)

如果有空哈希,它可能不会产生您期望的结果.