I am trying to merge two Hashes.I got the code from here . As you can see I want to add one more hobby to my list. There are many hobbies. When h1 is formed ,only one hobby was available. When the second hobby arrived I wanted to merge it with the previous hash.
The structure of the Hashes are :
h1 = {"students"=>[{"name"=>"bobby", "hobbies"=>[{"outdoor"=>"cycling"}]}]}
h2 = {"students"=>[{"name"=>"bobby", "hobbies"=>[{"indoor"=>"reading"}]}]}
I ran this code:
res = h1.merge(h2) {|key,val1,val2| val1.merge val2}
The error I got was:
undefined method `merge' for [{"name"=>"bobby", "hobbies"=>[{"outdoor"=>"cycling"}]}]:Array (NoMethodError)
So since array is involved, I don't know what to do. Any Help.
Required Output:
{"students"=>[{"name"=>"bobby", "hobbies"=>[{"outdoor"=>"cycling", "indoor"=>"reading"}]}]}
The built-in marge method cannot do what you want. You should write the original code to merge these structure like this.
def recursive_merge(h1, h2)
case h1
when Hash
(h1.keys + h2.keys).each do |key|
if h1.include?(key) && h2.include?(key) then
recursive_merge(h1[key], h2[key])
elsif h2.include?(key)
h1[key] = h2[key]
end
end
when Array
for i in 0...([h1.count, h2.count].max)
if i < h1.count && i < h2.count then
recursive_merge(h1[i], h2[i])
elsif i < h2.count then
h1[i] = h2[i]
end
end
end
end
recursive_merge(h1, h2)
puts h1
This method results the follwing output. Please note that this method overwrites h1 itself.
{"students"=>[{"name"=>"bobby", "hobbies"=>[{"outdoor"=>"cycling", "indoor"=>"reading"}]}]}
The answer on your question might be:
h1.merge(h2) { |k, v1, v2|
v1.map.with_index { |v1e, idx|
v1e['hobbies'].first.merge! v2[idx]['hobbies'].first
v1e
}
v1
}
#⇒ {
# "students" => [
# [0] {
# "hobbies" => [
# [0] {
# "indoor" => "reading",
# "outdoor" => "cycling"
# }
# ],
# "name" => "bobby"
# }
# ]
# }
But I would definitely redesign hobbies to be a hash, not an array of hashes, eliminating weird first
calls:
v1e['hobbies'].merge! v2[idx]['hobbies']
Hope it helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.