[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Mering an array of hashes

Luke Grimstrup

6/4/2008 10:59:00 AM

I have two arrays of hashes and I would like to merge them.

One array has the array of:
{:id, :name}

The other, an array of:
{:name, :other_attributes*}

I've been raking my brains for hours on this one. Is there anyone who
can suggest the best way to merge these two arrays so that I can get the
resulting array of:
{:id. :name, :other_attributes}

Thanks so much in advance.
--
Posted via http://www.ruby-....

11 Answers

Jesús Gabriel y Galán

6/4/2008 11:13:00 AM

0

On Wed, Jun 4, 2008 at 12:58 PM, Luke Grimstrup <luke.g@inner-fire.net> wrote:
> I have two arrays of hashes and I would like to merge them.
>
> One array has the array of:
> {:id, :name}
>
> The other, an array of:
> {:name, :other_attributes*}
>
> I've been raking my brains for hours on this one. Is there anyone who
> can suggest the best way to merge these two arrays so that I can get the
> resulting array of:
> {:id. :name, :other_attributes}

Is this what you are after? Not sure if I understood your description
correctly (an example of input and expected output would help):

irb(main):007:0> require 'generator'
irb(main):007:0> a = [{:id => 1}, {:id => 2}]
irb(main):007:0> b = [{:name => "a"}, {:name => "b"}]
irb(main):007:0> s = SyncEnumerator.new a,b
irb(main):007:0> s.map{|a,b| a.merge(b)}

=> [{:name=>"a", :id=>1}, {:name=>"b", :id=>2}]

Hope this helps,

Jesus.

Luke Grimstrup

6/4/2008 11:19:00 AM

0

Close, but not quite.

Here's an example:
hash #1: [{:name=>"File1.rar",
:id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
:id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
:id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]

hash #2 [{:name=>"File2.avi", :other_attributes =>"(350 MiB) - 2.85%
downloading at 0.00 B/s (UL at 0.00 B/s), stalled [error
(tracker-warning) - Tracker hasn't responded yet. Retrying...]"},
{:name=>"File1.rar", :other_attributes=>" (26.6 MiB) - 100% seeding at
0.00 B/s [0.23]"}, {:name=>"File3.avi", :other_attributes=>"(35.5 MiB) -
0.86% downloading at 0.00 B/s (UL at 0.00 B/s), stalled"}]

Note that the hashes I want to merge aren't necessarily at the same
index.
--
Posted via http://www.ruby-....

benjohn

6/4/2008 11:20:00 AM

0

> I have two arrays of hashes and I would like to merge them.
>
> One array has the array of:
> {:id, :name}
>
> The other, an array of:
> {:name, :other_attributes*}
>
> I've been raking my brains for hours on this one. Is there anyone who
> can suggest the best way to merge these two arrays so that I can get the
> resulting array of:
> {:id. :name, :other_attributes}

I'm very confused by your notation above. Sorry to sound picky, but would
you be able to make it more clear?

Cheers,
B


Luke Grimstrup

6/4/2008 11:29:00 AM

0

Sorry B, late at night here :p

array #1: [{:name=>"File1.rar",
:id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
:id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
:id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]

array #2 [{:name=>"File2.avi", :other_attributes =>"stuff"},
{:name=>"File1.rar", :other_attributes=>"stuff"}, {:name=>"File3.avi",
:other_attributes=>"stuff"}]

And I would like the resulting array to look like:
array #1: [{:other_attributes => "stuff", :name=>"File1.rar",
:id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
:id=>"58a658047ccb7333eb812da02dca9d84c1db2b41", :other_attributes =>
"stuff"}, {:name=>"File3.avi",
:id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310", :other_attributes =>
"stuff"}]

But I just have no idea how to do it. I'm sure there's an easy ruby way
to do it somehow..
--
Posted via http://www.ruby-....

benjohn

6/4/2008 11:56:00 AM

0

> Sorry B, late at night here :p
>
> array #1: [{:name=>"File1.rar",
> :id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
> :id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
> :id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]
>
> array #2 [{:name=>"File2.avi", :other_attributes =>"stuff"},
> {:name=>"File1.rar", :other_attributes=>"stuff"}, {:name=>"File3.avi",
> :other_attributes=>"stuff"}]
>
> And I would like the resulting array to look like:
> array #1: [{:other_attributes => "stuff", :name=>"File1.rar",
> :id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
> :id=>"58a658047ccb7333eb812da02dca9d84c1db2b41", :other_attributes =>
> "stuff"}, {:name=>"File3.avi",
> :id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310", :other_attributes =>
> "stuff"}]
>
> But I just have no idea how to do it. I'm sure there's an easy ruby way
> to do it somehow..

Ah, okay, that's clear, but pretty weird data :-)

id_rows = a.map {|r| r.values_at(:name, :id)}
other_att_rows = b.map {|r| r.values_at(:name, :other_attributes)}
name_to_attr_map = Hash[*other_att_rows.flatten]
output = id_rows.map {|r| Hash[:name, r[0], :id, r[1], :other_attributes,
name_to_attr_map[r[0]]]}

Will work, and can be readily improved (exercise for reader ;-) - it'll be
niceer without turning the data in to an array of rows as I do in first
two lines).


Uwe s Schirmer

6/4/2008 12:10:00 PM

0

I would do it like this:

a1 = [{:name=>"File1.rar",
:id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"},
{:name=>"File2.avi",
:id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"},
{:name=>"File3.avi",
:id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]
a2 = [{:name=>"File2.avi", :other_attributes =>"stuff"},
{:name=>"File1.rar", :other_attributes=>"stuff"},
{:name=>"File3.avi", :other_attributes=>"stuff"}]


a3 = Array.new
a1.each do |entry1|
a2.each do |entry2|
if entry1[:name].eql? entry2[:name]
a3.push(entry1.merge(entry2))
break
end
end
end
p a3


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

Luke Grimstrup

6/4/2008 12:11:00 PM

0

Ah, that does work too!

A friend of mine told me what I "should" be doing to get it working, but
left the exercise of the coding it up to me.

Here's the magic:
hash_b.each{|d| d.merge!(hash_a.select{|e| e[:name] == d[:name]}.first)}
--
Posted via http://www.ruby-....

Luke Grimstrup

6/4/2008 12:13:00 PM

0

Actually, complete code:
a1 = [{:name=>"File1.rar",
:id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
:id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
:id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]

a2 = [{:name=>"File2.avi", :other_attributes =>"(350 MiB) - 2.85%
downloading at 0.00 B/s (UL at 0.00 B/s), stalled [error
(tracker-warning) - Tracker hasn't responded yet. Retrying...]"},
{:name=>"File1.rar", :other_attributes=>" (26.6 MiB) - 100% seeding at
0.00 B/s [0.23]"}, {:name=>"File3.avi", :other_attributes=>"(35.5 MiB) -
0.86% downloading at 0.00 B/s (UL at 0.00 B/s), stalled"}]

a2.each{|d| d.merge!(a1.select{|e| e[:name] == d[:name]}.first)}

Luke Grimstrup wrote:
> Ah, that does work too!
>
> A friend of mine told me what I "should" be doing to get it working, but
> left the exercise of the coding it up to me.
>
> Here's the magic:
> hash_b.each{|d| d.merge!(hash_a.select{|e| e[:name] == d[:name]}.first)}

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

benjohn

6/4/2008 12:16:00 PM

0

> Actually, complete code:
> a1 = [{:name=>"File1.rar",
> :id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
> :id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
> :id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]
>
> a2 = [{:name=>"File2.avi", :other_attributes =>"(350 MiB) - 2.85%
> downloading at 0.00 B/s (UL at 0.00 B/s), stalled [error
> (tracker-warning) - Tracker hasn't responded yet. Retrying...]"},
> {:name=>"File1.rar", :other_attributes=>" (26.6 MiB) - 100% seeding at
> 0.00 B/s [0.23]"}, {:name=>"File3.avi", :other_attributes=>"(35.5 MiB) -
> 0.86% downloading at 0.00 B/s (UL at 0.00 B/s), stalled"}]
>
> a2.each{|d| d.merge!(a1.select{|e| e[:name] == d[:name]}.first)}

Hey - that comes out really cleanly. Cool.


David A. Black

6/4/2008 1:01:00 PM

0

Hi --

On Wed, 4 Jun 2008, Luke Grimstrup wrote:

> Actually, complete code:
> a1 = [{:name=>"File1.rar",
> :id=>"a3d80425a51a3a4cb2d7a3201439ef6cc3af5874"}, {:name=>"File2.avi",
> :id=>"58a658047ccb7333eb812da02dca9d84c1db2b41"}, {:name=>"File3.avi",
> :id=>"944f6a7c50a4a5cff0c28cb0f9158b16580b0310"}]
>
> a2 = [{:name=>"File2.avi", :other_attributes =>"(350 MiB) - 2.85%
> downloading at 0.00 B/s (UL at 0.00 B/s), stalled [error
> (tracker-warning) - Tracker hasn't responded yet. Retrying...]"},
> {:name=>"File1.rar", :other_attributes=>" (26.6 MiB) - 100% seeding at
> 0.00 B/s [0.23]"}, {:name=>"File3.avi", :other_attributes=>"(35.5 MiB) -
> 0.86% downloading at 0.00 B/s (UL at 0.00 B/s), stalled"}]
>
> a2.each{|d| d.merge!(a1.select{|e| e[:name] == d[:name]}.first)}
>
> Luke Grimstrup wrote:
>> Ah, that does work too!
>>
>> A friend of mine told me what I "should" be doing to get it working, but
>> left the exercise of the coding it up to me.
>>
>> Here's the magic:
>> hash_b.each{|d| d.merge!(hash_a.select{|e| e[:name] == d[:name]}.first)}

You can use #find rather than #select plus #first.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
See http://www.r... for details and updates!