Created
April 29, 2013 15:05
-
-
Save ScotterC/5482191 to your computer and use it in GitHub Desktop.
Hash deep find correction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A common method you'll find on the internet for a deep_find in a Hash | |
def deep_find(key) | |
key?(key) ? self[key] : self.values.inject(nil) {|memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) } | |
end | |
# Let's break this up without the ternarys | |
def deep_find(key) | |
if key?(key) | |
self[key] | |
else | |
self.values.inject(nil) do |memo, v| | |
if v.respond_to?(:deep_find) | |
memo ||= v.deep_find(key) | |
end | |
end | |
end | |
end | |
# The problem with the above is it can screw up badly with a hash that has values past the nested hashes | |
# such as: | |
# {:a => {:b => {:c => :stuff} }, :d => other_stuff } | |
# What will happen is memo will get assigned correctly but then the next inject will set memo to | |
# nil and the value will be lost | |
# A fix for this is to return memo if you got it and not spend any more time looking. | |
def deep_find(key) | |
if key?(key) | |
self[key] | |
else | |
self.values.inject(nil) do |memo, v| | |
return memo if memo | |
if v.respond_to?(:deep_find) | |
memo ||= v.deep_find(key) | |
end | |
end | |
end | |
end | |
# Shortened | |
def deep_find(key) | |
key?(key) ? self[key] : self.values.inject(nil) {|memo, v| return memo if memo; memo ||= v.deep_find(key) if v.respond_to?(:deep_find) } | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment