Reputation: 5148
Okay so this is a bit complex but I need to loop through this hash to find if each element meets one of following conditions:
The Value is a String
or
The Value is a Hash, containing Strings, Not Hashes
or
The Value is a Hash, containing Strings and/or Hashes
or
The Value is an Array
UPDATE:
Something very strange... [EDIT: this is because #collect is returning the hash's key-value pairs, which are arrays]
irb> my_hash['gd:name'].collect(&:class)
=> [Array, Array]
Looking at the hash below should the class of that inner element be a Hash, not an Array?
Inspected it looks like:
irb> my_hash['gd:name'].collect(&:inspect)
=> ["[\"gd:givenName\", {\"$t\"=>\"Thomas\"}]", "[\"gd:familyName\", {\"$t\"=>\"Chapin\"}]"]
BUT IT BEHAVES LIKE A HASH:
irb> my_hash['gd:name']['gd:givenName']
=> {"$t"=>"Thomas"}
irb> my_hash['gd:name']['gd:givenName']['$t']
=> "Thomas"
{
"gd:etag"=>"\"Rnk7fjVSLyt7I2A9WhVQEU4KRQI.\"",
"id"=>{
"$t"=>"da513d38e88d949"
},
"gd:name"=>{
"gd:givenName"=>{"$t"=>"Thomas"}, "gd:familyName"=>{"$t"=>"Chapin"}
},
"gd:phoneNumber"=>[
{
"rel"=>"mobile",
"$t"=>"(480) 703-4887"
}
],
"gd:email"=>[
{
"rel"=>"home",
"primary"=>"true",
"address"=>"[email protected]"
},
{
"rel"=>"work",
"address"=>"[email protected]"}
]
}
Upvotes: 1
Views: 752
Reputation: 35483
Examine Hash values.
Return true iff each:
A solution with some printing to show what's happening:
puts hash.each_pair.all?{|k,v|
puts "key #{k} = value #{v} class #{v.class}"
case v
when String, Array
true
when Hash
return false if v.empty?
v.each_pair.all?{|k2,v2|
puts "inner key #{k2} = value #{v2} class #{v2.class}"
case v2
when String, Hash
true
else
false
end
}
else
false
end
}
If you don't care to keep track of the keys, you can change #each_pair to #values
Upvotes: 1
Reputation: 1474
You can test the class of hash value.
hash.each do |key, value|
if value.is_a? String
# do String work
elsif value.is_a? Hash
#do Hash work
elsif value.is_a? Array
# do Array work
end
end
EDIT: updated with suggestion from Niklas B.
Upvotes: 1