RFC - Recursive Array Method call acting on element batches

I work for the Department of Redundancy Department and I'm thinking
there must be a better, more elegant way to doing the following:

With an array of 200 elements
Call a method to act on 10 elements at a time
Repeat until all elements are processed.
Return the processed array.

Here's my solution to the above:

__BEGIN__

class Array
  def process(method_obj, batch_size = 10, fin = [])
    if (this_batch = self.first(batch_size)).size > 0
      fin.concat method_obj.call(this_batch)
      (self - this_batch).process(method_obj, batch_size, fin)
    else
      return fin
    end
  end
end

def munge(ary)
  ary.collect { |e| e.+ 10 }
end

my_meth = method(:munge)

ARY = [1,2,3,4,5,6]
p ARY.process(my_meth, 2) # run my_meth against 2 elements at a time

__END__

The above produces: [11, 12, 13, 14, 15, 16]

This is just a trivial example, but, for what I'm actually doing
there's a limit of 100 items that can be processed by this mysterious
(dynamic) method, hence the need to "batch" process the array.

Does my solution scream newb? Anyone have a suggestion that would
"own me with easy"?

Thanks in advance for any comments.

Ben

Hi,

···

In message "Re: RFC - Recursive Array Method call acting on element batches" on Sun, 25 Nov 2007 02:35:02 +0900, rubydeckard@gmail.com writes:

I work for the Department of Redundancy Department and I'm thinking
there must be a better, more elegant way to doing the following:

With an array of 200 elements
Call a method to act on 10 elements at a time
Repeat until all elements are processed.
Return the processed array.

Hmm, how about

  ary = ... # array of 200 elements
  ary.each_slice(10).map{|x| ...}

in 1.9?

              matz.

unknown wrote:

With an array of 200 elements
Call a method to act on 10 elements at a time
Repeat until all elements are processed.
Return the processed array.

Pre ruby 1.9:

require 'enumerator'

def sum(arr)
  total = 0

  arr.each {|elmt| total += elmt}
  #faster than the ponderously slow inject method

  total
end

results =
arr = Array.new(15) {|i| i}
p arr

arr.each_slice(10) do |portion|
  results << sum(portion)
end

p results

--output:--
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
[45, 60]

···

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

Thanks for your input guys. That put me on the right track.

  def proc_array(method_obj, batch_size = 2)
    result = []
    self.each_slice(batch_size) do |batch|
      result.concat method_obj.call(batch)
    end
    result
  end

That turns out to be twice as fast as the recursive method. The only
trouble I experienced was getting each_slice into my class. Turns out
that there's an error with the ruby core library documentation
produced by RDoc. #each_slice is available via the *standard* library
'enumerator.rb', not the core module library Enumerable as is
documented at www.ruby-doc.org. Once I figured that out, all is
peachy keen.

Thanks,

Ben

Better:
  def proc_array(batch_size = 2, &method_obj)
    result =
    self.each_slice(batch_size) do |batch|
      result.concat method_obj.call(batch)
    end
    result
  end

Can be called as

...proc_array do |batch|
end

or

...proc_array(2, &method_obj)

Eivind.

···

On Nov 25, 2007 8:30 PM, <rubydeckard@gmail.com> wrote:

Thanks for your input guys. That put me on the right track.

  def proc_array(method_obj, batch_size = 2)
    result =
    self.each_slice(batch_size) do |batch|
      result.concat method_obj.call(batch)
    end
    result
  end