class Object def deep_clone Marshal.load(Marshal.dump(self)) end end class Hash # From: http://www.sameshirteveryday.com/2007/09/23/ruby-get-full-history-all-parents-of-a-hash-node # Author: Alex Gorbatchev # for further recursive hash methods see: # - http://snippets.dzone.com/posts/show/1908 # - http://snippets.dzone.com/posts/show/4706 def nested_key(desired_key, &block) return false unless Hash === self #return false unless self.is_a?(Hash) self.each_pair do |k,v| if k == desired_key or v.nested_key(desired_key, &block) yield(k,v) return true end end return false end def deep_values(key) # cf. http://snippets.dzone.com/posts/show/1908 hash = self.deep_clone ret = [] begin ar = [] result = hash.nested_key(key) { |k, v| ar << k } break unless result ar = ar.reverse hk = "" ar.size.times { |i| hk << "[ar[#{i}]]" } #str = "hash" << hk << " rescue nil" str = "hash" << hk # get value for hash key hk ret << eval(str) # delete the hash key key_to_delete = [ar.pop] hk = "" ar.size.times { |i| hk << "[ar[#{i}]]" } str = "hash" << hk str = str << ".delete(key_to_delete.first)" eval(str) end while result hash.clear # optional ret end def deep_delete(key) hash = self begin ar = [] result = hash.nested_key(key) { |k, v| ar << k } break unless result ar = ar.reverse # delete the hash key key_to_delete = [ar.pop] hk = "" ar.size.times { |i| hk << "[ar[#{i}]]" } str = "hash" << hk str = str << ".delete(key_to_delete.first)" eval(str) end while result end end puts hash = { :level_1 => { :level_2 => { :search => 'test1', :level_3 => { :search => 'test2', :level_4 => {:search => 'test3'} } } } } require 'pp' p hash puts pp hash puts hash.nested_key(:search) { |k, v| puts "#{k} :: #{v.inspect}" } # prints out... # search :: "test1" # level_2 :: {:search=>"test1", :level_3=>{:search=>"test2", :level_4=>{:search=>"test3"}}} # level_1 :: {:level_2=>{:search=>"test1", :level_3=>{:search=>"test2", :level_4=>{:search=>"test3"}}}} puts puts "DEEP VALUES" p hash.deep_values(:search) #=> ["test1", "test2", "test3"] puts puts "DEEP VALUES DELETED" hash.deep_delete(:search) p hash #=> {:level_1=>{:level_2=>{:level_3=>{:level_4=>{}}}}} puts puts "DEEP VALUES" p hash.deep_values(:search) #=> []
You need to create an account or log in to post comments to this site.