Tricky ruby array grouping method

I want to define a method that performs the following operation:

Given an array: array = [a, b, c, d, e, f, g, h, i] My imaginary method (let's call it nest_by) would produce these results array.nest_by(2) => [[a, b], [c, d], [d, e], [f, g], [h, i]] array.nest_by(3) => [[a, b, c], [d, e, f], [g, h, i]] array.nest_by(4) => [[a, b, c, d], [e, f, g, h], [i, nil, nil, nil]]

The contents of the array can be anything (including array's themselves). This is sort of like the rails Array.in_groups_of(n), but uses the array.size to determine the number of elements in each new nested array.

Any thoughts?

Daniel

Ack, what I explained WAS array.in_groups_of(n).

What I'm ACTUALLY looking for is: array.nest_by(2) => [[a, b, c, d, e], [f, g, h, i]] array.nest_by(3) => [[a, b, c], [d, e, f], [g, h, i]] array.nest_by(4) => [[a, b, c], [d, e], [f, g], [h, i]]

Where nest_by(n) produces n nested arrays. In the case of 2 and 4 when it's not an balanced match, distribute the extras amongst first arrays.

This is probably better posted in ruby-talk. Here's a stab, though:

class Array   def nest_by(group_count)     in_groups_of(size / group_count + size % group_count).collect(&:compact)   end end

~ j.

you could probably golf this, but:

require 'enumerator' class Array     def nest_by(length_of_out)         num_per_element, remainder = self.length.divmod(length_of_out);         temp=         self.reverse.each_slice(num_per_element) { |slice| temp << slice}         if remainder>0             temp[-2]+= temp[-1]             temp.slice!(-1)         end         return temp.reverse     end end

Thanks gene.tani, you got me close enough. The only problem with your solution was that if there were 2 remaining elements, I wanted those distributed among the first two nested array, not all in the first array. Here's the finished solution for what I was looking for:

class Array   def in_n_groups(n)     num_per_element, remainder = self.length.divmod(n);     orig = self.dup     temp =     until orig.empty?       if remainder > 0         temp << orig.slice!(0, num_per_element+1)         remainder -= 1       else         temp << orig.slice!(0, num_per_element)       end     end     return temp   end end

array = %w{ a b c d e f g h i j k } array => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]

array.in_n_groups(2) => [["a", "b", "c", "d", "e", "f"], ["g", "h", "i", "j", "k"]]

array.in_n_groups(3) => [["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i", "j", "k"]]

array.in_n_groups(4) => [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k"]]

Great for distributing long lists of data between balanced table columns. Especially when you only want n columns.

Thanks everyone for helping.

Daniel