Find key/value pairs deep inside a hash containing an arbitrary number of nested hashes and arrays
Here's a simple recursive solution:
def nested_hash_value(obj,key) if obj.respond_to?(:key?) && obj.key?(key) obj[key] elsif obj.respond_to?(:each) r = nil obj.find{ |*a| r=nested_hash_value(a.last,key) } r endendh = { foo:[1,2,[3,4],{a:{bar:42}}] }p nested_hash_value(h,:bar)#=> 42
No need for monkey patching, just use Hashie gem: https://github.com/intridea/hashie#deepfind
user = { name: { first: 'Bob', last: 'Boberts' }, groups: [ { name: 'Rubyists' }, { name: 'Open source enthusiasts' } ]}user.extend Hashie::Extensions::DeepFinduser.deep_find(:name) #=> { first: 'Bob', last: 'Boberts' }
For arbitrary Enumerable objects, there is another extension available, DeepLocate: https://github.com/intridea/hashie#deeplocate
Combining a few of the answers and comments above:
class Hash def deep_find(key, object=self, found=nil) if object.respond_to?(:key?) && object.key?(key) return object[key] elsif object.is_a? Enumerable object.find { |*a| found = deep_find(key, a.last) } return found end endend