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!
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.
This should be a one pass operation that works with nested arrays and hashes:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With