cheeseandpepper cheeseandpepper - 1 month ago 15
Ruby Question

Deeply compact nested hash in ruby?

Given the following hash structure...

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


I'd like to be able to return...

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


So the rules would be

1) Remove any key that points to a
nil
,
{}
, or
[]
value

2) Remove any key that leads to value which points to an empty value (example
c:
from the original hash)

3) Preserve the outer key if one or more inner keys point to a non empty value, but remove inner keys that point to an empty value. (see
f:
and notice that
f2:
is removed)

Any help would be appreciated!

Answer

You could have some fun with monkey-patching the core classes involved:

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

It's an unusual thing to want to do, but if you do need it done writing a method like crush might help.

Comments