class Hash
def fetch_all(key)
results = []
hashfinder = lambda {|h|
arrayfinder = lambda {|a|
a.each do |v|
hashfinder[v] if v.is_a?(Hash)
arrayfinder[v] if v.is_a?(Array)
end
}
if h.has_key?(key)
results << h.fetch(key)
end
h.values.each do |v|
hashfinder[v] if v.is_a?(Hash)
arrayfinder[v] if v.is_a?(Array)
end
}
hashfinder.call(self)
results
end
end
Refactorings
No refactoring yet !
jes5199
March 21, 2008, March 21, 2008 00:20, permalink
well, since we're already reopening standard classes, I thought it might make sense to move the Array logic into class Array. Now we have simple recursion of methods, instead of having to make private functions.
class Hash
def fetch_all(key)
return [] if not self.has_key?(key)
value = self.fetch(key)
[ value ] + [ value ].fetch_all(key)
end
end
class Array
def fetch_all(key)
self.find_all{|x| x.respond_to? :fetch_all} \
.map{|x| x.fetch_all(key) } \
.inject( [] ){|a,b| a + b }
end
end
Strattera ohne rezept
June 22, 2011, June 22, 2011 14:54, permalink
Those who know don’t speak. Those who speak don’t know.
I wanted a Hash#fetch that would return all matches for a particular key in a hash with nested hashes and arrays, and this is what I came up with. I'm pretty new to Ruby, so I can't help but think there's a better way to do it.