ruby 中的深度紧凑嵌套哈希?

che*_*per 3 ruby hash ruby-on-rails

给定以下哈希结构...

{
  a: nil,
  b: [],
  c: {c1: {c2: nil}},
  d: [{d1: "Value!"}],
  e: "Value!",
  f: {f1: {f2: nil, f3: "Value!"}}
}
Run Code Online (Sandbox Code Playgroud)

我希望能够回来...

{
  d: [{d1: "Value!"}],
  e: "Value!",
  f: {f1: {f3: "Value!"}}
}
Run Code Online (Sandbox Code Playgroud)

因此,规则将是
1) 删除任何指向nil{}[]值的键
2) 删除导致指向空值的值的任何键(c:原始哈希的示例)
3) 如果存在一个或多个,则保留外部键内部键指向非空值,但删除指向空值的内部键。(请参阅f:并注意f2:已删除的内容)

任何帮助,将不胜感激!

tad*_*man 8

您可以通过猴子修补所涉及的核心类来获得一些乐趣:

class Object
  def crush
    self
  end
end

class Array
  def crush
    r = map(&:crush).compact

    r.empty? ? nil : r
  end
end

class Hash
  def crush
    r = each_with_object({ }) do |(k, v), h|
      if (_v = v.crush)
        h[k] = _v
      end
    end

    r.empty? ? nil : r
  end
end
Run Code Online (Sandbox Code Playgroud)

这是一件不寻常的事情,但如果你确实需要这样做,那么编写一个类似的方法crush可能会有所帮助。


Int*_*tss 6

这应该是一个适用于嵌套数组和哈希的一次性操作:

CRUSHABLE = [nil, [], {}].freeze
def crush(thing)
  if thing.is_a?(Array)
    thing.each_with_object([]) do |v, a|
      v = crush(v)
      a << v unless CRUSHABLE.include?(v)
    end
  elsif thing.is_a?(Hash)
    thing.each_with_object({}) do |(k,v), h|
      v = crush(v)
      h[k] = v unless CRUSHABLE.include?(v)
    end
  else
    thing
  end
end

Run Code Online (Sandbox Code Playgroud)