Ruby中的深度压缩嵌套哈希?

enyaitl3  于 2023-06-22  发布在  Ruby
关注(0)|答案(3)|浏览(74)

下面的hash结构...

{
  a: nil,
  b: [],
  c: {c1: {c2: nil}},
  d: [{d1: "Value!"}],
  e: "Value!",
  f: {f1: {f2: nil, f3: "Value!"}}
}

我希望能够返回...

{
  d: [{d1: "Value!"}],
  e: "Value!",
  f: {f1: {f3: "Value!"}}
}

所以规则是
1)删除指向nil{}[]值的所有键
2)删除任何指向空值的值的键(例如原始哈希中的c:
3)如果一个或多个内部键指向非空值,则保留外部键,但删除指向空值的内部键。(参见f:,注意f2:已被删除)
任何帮助将不胜感激!

pbwdgjma

pbwdgjma1#

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

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

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

g0czyy6m

g0czyy6m2#

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

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
dgsult0t

dgsult0t3#

def deep_compact(hash)
    res_hash = hash.map do |key, value|
      value = deep_compact(value) if value.is_a?(Hash)

      value = nil if [{}, []].include?(value)
      [key, value]
    end

    res_hash.to_h.compact
  end

相关问题