DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Extracting All Keys From A Multi-dimensional Hash
Extract all complete key sequences from a multi-dimensional hash (with the last key not pointing to another hash; cf. h[1][2][3] vs h[1][2][3][4] below).
class Hash
def extract_keys
keys = []
each_pair do |k1, v1|
if v1.is_a?(Hash)
v1.each_pair { |k2, v2|
if !v2.is_a?(Hash) then keys << [k1, k2]; next end
v2.each_pair { |k3, v3|
if !v3.is_a?(Hash) then keys << [k1, k2, k3]; next end
v3.each_pair { |k4, v4|
if !v4.is_a?(Hash) then keys << [k1, k2, k3, k4]; next end
v4.each_pair { |k5, v5|
if !v5.is_a?(Hash) then keys << [k1, k2, k3, k4, k5]; next end
v5.each_pair { |k6, v6|
if !v6.is_a?(Hash) then keys << [k1, k2, k3, k4, k5, k6]; next end
# add more v[n].each_pair ... loops to process more hash dimensions
} } } } } # "}" * 5
else
keys << [k1]
end
end
keys
end
def all_values
extract_keys.map do |subar|
key = ""
subar.size.times { |i| key << "[subar[#{i}]]" }
hash_str = "self" << key << " rescue nil" # example: "self[subar[0]][subar[1]][subar[2]][subar[3]] rescue nil"
hash_value = eval(hash_str)
end
end
#-------------------------
# Find every path and it's value in a Hash, http://snippets.dzone.com/posts/show/3565
# Author: Florian Aßmann
def each_path
raise ArgumentError unless block_given?
self.class.each_path(self) { |path, object| yield(path, object) }
end
protected
#def self.each_path(object, path = '', &block)
def self.each_path(object, path = [], &block) # alternative
if object.is_a?(Hash)
object.each do |key, value|
#self.each_path(value, "#{ path }#{ key }/", &block)
self.each_path(value, [path , key].flatten, &block) # alternative
end
else
yield(path, object)
end
end
end
h = {"a"=>"b", "c"=>"d", 1=>{2=>{"e"=>"f", 3=>{4=>"value"}}}}
puts h[1][2].class # Hash
puts h[1][2]["e"].class # String
extracted_keys = h.extract_keys
puts extracted_keys.inspect # [["a"], [1, 2, "e"], [1, 2, 3, 4], ["c"]]
puts h[1][2].has_key?("e") # true
puts extracted_keys.include?([1, 2, "e"]) # true
h = {700=>{4=>"value"}, "a"=>"b", 3=>{4=>"value"}, "c"=>"d", 1=>{2=>{"e"=>"f", 3=>{4=>"value"}, 300=>{4=>"value"}}}}
p h
p h.extract_keys #=> [["a"], [1, 2, "e"], [1, 2, 300, 4], [1, 2, 3, 4], ["c"], [700, 4], [3, 4]]
p h.all_values #=> ["b", "f", "value", "value", "d", "value", "value"]
#-----------------
paths = []
complex_hash = Hash[
:a => { :aa => '1', :ab => '2' },
:b => { :ba => '3', :bb => '4' }
]
complex_hash.each_path { |path, value| paths << [ path, value ] }
p paths # => [[[:b, :ba], "3"], [[:b, :bb], "4"], [[:a, :ab], "2"], [[:a, :aa], "1"]]
puts
h = {"a"=>"b", "c"=>"d", 1=>{2=>{"e"=>"f", 3=>{4=>"value"}}}}
h = {"a"=>"b", "l" => lambda { |x| x+1 }, 1=>{2=>{"e"=>"f", 3=>{4=>"value"}}}}
h = {700=>{4=>"value"}, "a"=>"b", nil => "NILVALUE", 3=>{4=>"value"}, "c"=>"d", 1=>{2=>{"e"=>"f", 3=>{4=>"value"}, 300=>{4=>"value"}}}}
p h
p h.extract_keys
keys = []
h.each_path { |path, value| keys << path }
p keys # complete key sequences (with last key not pointing to another hash)
paths = []
h.each_path { |path, value| paths << [ path, value ] }
p paths # complete key sequences plus values
vals = []
h.each_path { |path, value| vals << value }
p vals # all values of complete key sequences
p h.all_values # same






Comments
Snippets Manager replied on Mon, 2012/05/07 - 2:23pm
Snippets Manager replied on Sun, 2006/01/29 - 5:07pm
Snippets Manager replied on Mon, 2012/05/07 - 2:23pm
class Hash def extract_keys(keys = [], temp = []) temp = temp.dup temp2 = temp.dup self.each { |key, value| if value.class != Hash temp << key keys << temp #puts temp.inspect temp = [] end } temp = temp2 self.each { |key, value| if value.class == Hash temp << key keys = value.extract_keys(keys, temp) end } keys end endSnippets Manager replied on Sun, 2006/01/29 - 5:07pm
Snippets Manager replied on Mon, 2012/05/07 - 2:23pm
class Hash def extract_keys keys = [] self.each { |key, value| if value.class == Hash keys << value.extract_keys else keys << key end } keys.flatten end end puts h.extract_keys.inspect