Advanced array merging

Hi everyone,

I'm looking for the fastest way (or the version with the least code!) to
consolidate a couple of arrays.

Basically, what a dump of what I have is this:

[[#<Ifinoctets_26 id: 2476, dtime: "2009-04-28 00:00:34", counter:
675392602>, #<Ifinoctets_26 id: 2476, dtime: "2009-04-28 00:05:34",
counter: 652224867>, #<Ifinoctets_26 id: 2476, dtime: "2009-04-28
00:10:34", counter: 637505981>, #<Ifinoctets_26 id: 2476, dtime:
"2009-04-28 00:15:34", counter: 813981324>, #<Ifinoctets_26 id: 2476,
dtime: "2009-04-28 00:20:34", counter: 753826918>],

[#<Ifinoctets_26 id: 2477, dtime: "2009-04-28 00:00:37", counter:
287888720>, #<Ifinoctets_26 id: 2477, dtime: "2009-04-28 00:05:37",
counter: 260326966>, #<Ifinoctets_26 id: 2477, dtime: "2009-04-28
00:10:37", counter: 287575144>, #<Ifinoctets_26 id: 2477, dtime:
"2009-04-28 00:15:37", counter: 341606600>, #<Ifinoctets_26 id: 2477,
dtime: "2009-04-28 00:20:37", counter: 305102837>],

[#<Ifinoctets_28 id: 2484, dtime: "2009-04-28 00:00:36", counter:
2976043831>, #<Ifinoctets_28 id: 2484, dtime: "2009-04-28 00:05:36",
counter: 2904676029>, #<Ifinoctets_28 id: 2484, dtime: "2009-04-28
00:10:36", counter: 2901969681>, #<Ifinoctets_28 id: 2484, dtime:
"2009-04-28 00:15:36", counter: 2827196523>, #<Ifinoctets_28 id: 2484,
dtime: "2009-04-28 00:20:36", counter: 2532538201>]]

I need to be able to grab the first record of each array (that happens
to be within the outer array) and merge them into one, keeping the
class, ID, and dtime of the first of the three and the SUMMED counter of
all three. In reality there could be anywhere between 2 and 30 arrays in
there each with any number of records. So let's say we have:

#<Ifinoctets_1 id: 100, dtime: "2009-04-28 00:00:34", counter: 500>

···

+
#<Ifinoctets_2 id: 111, dtime: "2009-04-28 00:00:37", counter: 1000>
+
#<Ifinoctets_3 id: 122, dtime: "2009-04-28 00:00:36", counter: 500>

=

#<Ifinoctets_1 id: 100, dtime: "2009-04-28 00:00:34", counter: 2000>
--
Posted via http://www.ruby-forum.com/.

pseudocode:

def add_octets(x, y)
  ret = x.dup
  ret.counter += y.counter
  ret
end

ary.inject {|e,i| add_octets(e,i)}

martin

···

On Wed, Apr 29, 2009 at 11:07 PM, Jack Bauer <realmadrid2727@yahoo.es> wrote:

Hi everyone,

I'm looking for the fastest way (or the version with the least code!) to
consolidate a couple of arrays.

Basically, what a dump of what I have is this:

[[#<Ifinoctets_26 id: 2476, dtime: "2009-04-28 00:00:34", counter:
675392602>, #<Ifinoctets_26 id: 2476, dtime: "2009-04-28 00:05:34",
counter: 652224867>, #<Ifinoctets_26 id: 2476, dtime: "2009-04-28
00:10:34", counter: 637505981>, #<Ifinoctets_26 id: 2476, dtime:
"2009-04-28 00:15:34", counter: 813981324>, #<Ifinoctets_26 id: 2476,
dtime: "2009-04-28 00:20:34", counter: 753826918>],

[#<Ifinoctets_26 id: 2477, dtime: "2009-04-28 00:00:37", counter:
287888720>, #<Ifinoctets_26 id: 2477, dtime: "2009-04-28 00:05:37",
counter: 260326966>, #<Ifinoctets_26 id: 2477, dtime: "2009-04-28
00:10:37", counter: 287575144>, #<Ifinoctets_26 id: 2477, dtime:
"2009-04-28 00:15:37", counter: 341606600>, #<Ifinoctets_26 id: 2477,
dtime: "2009-04-28 00:20:37", counter: 305102837>],

[#<Ifinoctets_28 id: 2484, dtime: "2009-04-28 00:00:36", counter:
2976043831>, #<Ifinoctets_28 id: 2484, dtime: "2009-04-28 00:05:36",
counter: 2904676029>, #<Ifinoctets_28 id: 2484, dtime: "2009-04-28
00:10:36", counter: 2901969681>, #<Ifinoctets_28 id: 2484, dtime:
"2009-04-28 00:15:36", counter: 2827196523>, #<Ifinoctets_28 id: 2484,
dtime: "2009-04-28 00:20:36", counter: 2532538201>]]

I need to be able to grab the first record of each array (that happens
to be within the outer array) and merge them into one, keeping the
class, ID, and dtime of the first of the three and the SUMMED counter of
all three. In reality there could be anywhere between 2 and 30 arrays in
there each with any number of records. So let's say we have:

#<Ifinoctets_1 id: 100, dtime: "2009-04-28 00:00:34", counter: 500>
+
#<Ifinoctets_2 id: 111, dtime: "2009-04-28 00:00:37", counter: 1000>
+
#<Ifinoctets_3 id: 122, dtime: "2009-04-28 00:00:36", counter: 500>

=

#<Ifinoctets_1 id: 100, dtime: "2009-04-28 00:00:34", counter: 2000>

Jack Bauer wrote:

Hi everyone,

I'm looking for the fastest way (or the version with the least code!) to
consolidate a couple of arrays.

Those two requirements are often at odds with each other. For instance,
"inject" and "fastest" should not be used in the same sentence.

result =

arr.each do |sub_arr|
  counter_total = 0

  sub_arr.each do |obj|
    counter_total += obj.counter
  end

  sub_arr[0].counter = counter_total
  result << sub_arr[0] #or result << [sub_arr[0]]
end

···

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

Those two requirements are often at odds with each other. For instance,
"inject" and "fastest" should not be used in the same sentence.

result =

arr.each do |sub_arr|
  counter_total = 0

  sub_arr.each do |obj|
    counter_total += obj.counter
  end

  sub_arr[0].counter = counter_total
  result << sub_arr[0] #or result << [sub_arr[0]]
end

Thanks, 7stud. I forgot to mention in my description that after it did
the sum of the first item in each of the 3 subarrays to move on and do
all the second items, then the third, etc. Using yours as a base I ended
up with:

index = 0
array[0].length.times do
  counter_total = 0
  array.each do |sub_array|
    counter_total += sub_array[index].counter
  end
  array[0][index].counter = counter_total
  data_stream_out << array[0][index]
  index += 1
end

Works like a charm and enormously faster than what I was doing before I
posted this thread. Before I asked for help here I was using inject and
the calculation was taking 28 seconds to complete. This one took 4 and
there were about 2,000 more records this time too.

···

--
Posted via http://www.ruby-forum.com/\.

Jack Bauer wrote:

Thanks, 7stud. I forgot to mention in my description that after it did
the sum of the first item in each of the 3 subarrays

Whoops. That's not what my code does--it sums the totals within one
array. I did a vertical traversal rather than a horizontal traversal.

move on and do
all the second items, then the third, etc. Using yours as a base I ended
up with:

index = 0
array[0].length.times do
  counter_total = 0
  array.each do |sub_array|
    counter_total += sub_array[index].counter
  end
  array[0][index].counter = counter_total
  data_stream_out << array[0][index]
  index += 1
end

Works like a charm and enormously faster than what I was doing before I
posted this thread. Before I asked for help here I was using inject and
the calculation was taking 28 seconds to complete. This one took 4 and
there were about 2,000 more records this time too.

I read your original post again and with all the talk of merging and
summing, I decided I have no idea what you are trying to do. If you've
got what you want--great!

···

--
Posted via http://www.ruby-forum.com/\.