recursive merge for hash

G

goodieboy

Hi,

Does anyone know of a good recursive merge method for Hashes? I'd like
to be able to do something like:

new_h = first.merge_r(second).merge_r(third)

... everything would be a copy, and hashes applied later in the
sequence override the previous finally, returning a completely new
hash... is there something out there like this?

Thanks,
Matt
 
F

Farrel Lifson

Hi,

Does anyone know of a good recursive merge method for Hashes? I'd like
to be able to do something like:

new_h = first.merge_r(second).merge_r(third)

... everything would be a copy, and hashes applied later in the
sequence override the previous finally, returning a completely new
hash... is there something out there like this?

new_h = first.merge(second).merge(third)

Farrel
 
G

goodieboy

Thanks. But the only problem with that is, the overriding hash will
completely destroy *all* of the values in the original. So if I want
to just override one value, I get only one value. In this example,
"Sam" is lost:

first = {
:data=>{
:name=>{
:first=>'Sam',
:middle=>'I',
:last=>'am'
}
}
}

second={
:data=>{
:name=>{
:middle=>'you',
:last=>'are'
}
}
}
all_new = first.merge(second)

puts all_new.inspect
 
J

Jimmy Kofler

M.W. Mitchell said:
Thanks. But the only problem with that is, the overriding hash will
completely destroy *all* of the values in the original. So if I want
to just override one value, I get only one value. In this example,
"Sam" is lost:

first = {
:data=>{
:name=>{
:first=>'Sam',
:middle=>'I',
:last=>'am'
}
}
}

second={
:data=>{
:name=>{
:middle=>'you',
:last=>'are'
}
}
}
all_new = first.merge(second)

puts all_new.inspect


How about Hash#deep_merge, http://snippets.dzone.com/posts/show/4706 ?

Cheers,
j.k.
 
S

Stefan Rusterholz

Jimmy said:
How about Hash#deep_merge, http://snippets.dzone.com/posts/show/4706 ?

Cheers,
j.k.

The question came up on IRC recently and I remembered this post. But I
wonder why the snippet does it in such a complicated way. Alternative:
merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2,
&merger) : v2 }
first.merge(second, &merger)

Regards
Stefan
 
J

Jimmy Kofler

Stefan said:
The question came up on IRC recently and I remembered this post. But I
wonder why the snippet does it in such a complicated way. Alternative:
merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2,
&merger) : v2 }
first.merge(second, &merger)

Regards
Stefan

Well, maybe it's a bit easier to modify or extend the verbose version.

For example:

class Hash
def keep_merge(hash)
target = dup
hash.keys.each do |key|
if hash[key].is_a? Hash and self[key].is_a? Hash
target[key] = target[key].keep_merge(hash[key])
next
end
#target[key] = hash[key]
target.update(hash) { |key, *values| values.flatten.uniq }
end
target
end
end


first = {
:data=>{
:name=>{
:first=>'Sam',
:middle=>'I',
:last=>'am'
}
}
}

second={
:data=>{
:name=>{
:middle=>'you',
:last=>'are'
}
}
}

p first.keep_merge(second)
#=> {:data=>{:name=>{:first=>"Sam", :middle=>["I", "you"],
:last=>["am", "are"]}}}

Anyway, a nice refactoring example!


Cheers,
j. k.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top