# Tricky ruby array grouping method

**URL:** <https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386>\
**Category:** Rails\
**Created:** [July 13, 2007, 10:53pm UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386 "2007-07-13T22:53:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![danlunde](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e36b37/32.png) [@danlunde](https://www.ruby-forum.com/u/danlunde)\
**Post date:** [July 13, 2007, 10:53pm UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386/1 "2007-07-13T22:53:49Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![danlunde](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e36b37/32.png) [@danlunde](https://www.ruby-forum.com/u/danlunde)\
**Post date:** [July 14, 2007, 12:00am UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386/2 "2007-07-14T00:00:56Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![danlunde](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e36b37/32.png) [@danlunde](https://www.ruby-forum.com/u/danlunde)\
**Post date:** [July 14, 2007, 2:00am UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386/3 "2007-07-14T02:00:05Z")

</div>

On 7/13/07, danlunde [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 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.

---

<div class="post-metadata">

**Author:** ![danlunde](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e36b37/32.png) [@danlunde](https://www.ruby-forum.com/u/danlunde)\
**Post date:** [July 16, 2007, 10:09pm UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386/4 "2007-07-16T22:09:08Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![danlunde](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e36b37/32.png) [@danlunde](https://www.ruby-forum.com/u/danlunde)\
**Post date:** [July 14, 2007, 7:31am UTC](https://www.ruby-forum.com/t/tricky-ruby-array-grouping-method/109386/5 "2007-07-14T07:31:32Z")

</div>

On Jul 13, 2:59 pm, danlunde [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 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]]

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
