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-forum.com/.
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.
···
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}
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
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-forum.com/.
Sorry B, late at night here
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-forum.com/.
Sorry B, late at night here
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).
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-forum.com/.
You already got other solutions, but here is another one:
irb(main):001:0> a = [{:id => 1, :name => "a"}, {:id => 2, :name => "b"}]
irb(main):002:0> b = [{:other => "other_b_data", :name => "b"},
{:other => "other_a_data", :name => "a"}]
irb(main):003:0> h = Hash.new {|h,k| h[k] = {}}
irb(main):013:0> (a + b).each {|data| h[data[:name]].merge!(data)}
irb(main):015:0> h.values
=> [{:other=>"other_a_data", :name=>"a", :id=>1},
{:other=>"other_b_data", :name=>"b", :id=>2}]
I haven't measured the time, but this might have better performance
than finding in the second array by
name every time, since here we are accessing a hash by that key.
Hope this helps,
Jesus.
···
On Wed, Jun 4, 2008 at 1:18 PM, Luke Grimstrup <luke.g@inner-fire.net> wrote:
Close, but not quite.
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-forum.com/.
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-forum.com/\.
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.