[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

recursive merge for hash

goodieboy

2/15/2008 3:37:00 PM

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

5 Answers

Farrel Lifson

2/15/2008 3:48:00 PM

0

On 15/02/2008, goodieboy <goodieBoy@gmail.com> wrote:
> 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

goodieboy

2/15/2008 3:57:00 PM

0

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


On Feb 15, 10:47 am, "Farrel Lifson" <farrel.lif...@gmail.com> wrote:
> On 15/02/2008, goodieboy <goodie...@gmail.com> wrote:
>
> > 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

Jimmy Kofler

2/16/2008 1:52:00 PM

0

> M.W. Mitchell wrote:
> 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... ?

Cheers,
j.k.

--
Posted via http://www.ruby-....

Stefan Rusterholz

2/19/2008 8:52:00 PM

0

Jimmy Kofler wrote:
>> M.W. Mitchell wrote:
>> 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... ?
>
> 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
--
Posted via http://www.ruby-....

Jimmy Kofler

2/21/2008 3:52:00 PM

0

> Stefan Rusterholz wrote:
> Jimmy Kofler wrote:
>>> M.W. Mitchell wrote:
>>> 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... ?
>>
>> 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

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.

--
Posted via http://www.ruby-....