Recently, while adding missing functionality for the i18n-js gem I’ve stumbled into a problem. I needed to have a method to “deep reject” keys in the hash. There are some examples in the wild doing that, but they all solve this problem by adding a new method to the Hash class. I wanted a generic method, which would take the hash as an argument.
After some head scratching, tinkering and tweaking, I’ve come up with a correct solution (at least I think it’s correct). Here it is:
def self.deep_reject(hash, &block)
hash.each_with_object({}) do |(k, v), memo|
unless block.call(k, v)
if v.is_a?(Hash)
memo[k] = deep_reject(v, &block)
else
memo[k] = v
end
end
end
end
You use it like this:
hash = {:a => {:b => 1, :c => 2}}
result = deep_reject(hash) { |k, v| k == :b }
result # => {:a => {:c => 2}}