# Grouping by twos

**URL:** <https://rubytalk.org/t/grouping-by-twos/2388>\
**Category:** ruby-talk\
**Created:** [20 October 2002 22:51 UTC](https://rubytalk.org/t/grouping-by-twos/2388 "2002-10-20T22:51:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [20 October 2002 22:51 UTC](https://rubytalk.org/t/grouping-by-twos/2388/1 "2002-10-20T22:51:58Z")

</div>

Another of those trivial little problems that I obsess about finding  
the Proper way to do - what’s a nice, idiomatic Ruby way to go from  
[a,b,c,d…] to [[a,b],[c,d],[e,f],…]? Note that I want to  
preserve the ordering, so to\_hash won’t work.

One way I thought of was  
b = []  
while a[0] do  
b \<\< [a.shift, a.shift]  
end

which works but doesn’t look particularly elegant.

martin

---

<div class="post-metadata">

**Author:** ![Dave\_Thomas](https://avatars.discourse-cdn.com/v4/letter/d/439d5e/32.png) [@Dave\_Thomas](https://rubytalk.org/u/Dave_Thomas)\
**Post date:** [20 October 2002 23:41 UTC](https://rubytalk.org/t/grouping-by-twos/2388/2 "2002-10-20T23:41:36Z")

</div>

[martindemello@yahoo.com](mailto:martindemello@yahoo.com) (Martin DeMello) writes:

> Another of those trivial little problems that I obsess about finding  
> the Proper way to do - what’s a nice, idiomatic Ruby way to go from  
> [a,b,c,d…] to [[a,b],[c,d],[e,f],…]? Note that I want to  
> preserve the ordering, so to\_hash won’t work.
> 
> One way I thought of was  
> b =   
> while a[0] do  
> b \<\< [a.shift, a.shift]  
> end

This isn’t much better, but

```
 b = []
 b << a.slice!(0,2) until a.empty?

```

Cheers

Dave

---

<div class="post-metadata">

**Author:** ![Allen\_Mitchell](https://avatars.discourse-cdn.com/v4/letter/a/ecd19e/32.png) [@Allen\_Mitchell](https://rubytalk.org/u/Allen_Mitchell)\
**Post date:** [21 October 2002 01:07 UTC](https://rubytalk.org/t/grouping-by-twos/2388/3 "2002-10-21T01:07:38Z")

</div>

I ran into the same requirement and I solved it by extending the Array  
class. Have a look…

class Array

> **···**
>
> #---------------------------------------------------------------------  
> # each\_group  
> #---------------------------------------------------------------------  
> def each\_group ( sizeof )  
> limitOf = length-1  
> 0.step( limitOf, sizeof ) { |i| yield( self[i,sizeof] ) }  
> end
> 
> ```
> #---------------------------------------------------------------------
> # collect_each_group
> #---------------------------------------------------------------------
> def collect_each_group ( sizeof )
> rtn = []
> limitOf = length-1
> 0.step( limitOf, sizeof ) { |i| rtn << yield( self[i,sizeof] ) }
> rtn
> end
> 
> ```
> 
> end
> 
> a = [1,2,3,4,5,6,7,8,9,10]  
> b = a.collect\_each\_group(2) { |items| items }  
> and b = [[1,2],[3,4],[5,6],[7,8],[9,10]]
> 
> Hope it helps…
> 
> -----Original Message-----  
> From: Martin DeMello [[mailto:martindemello@yahoo.com](mailto:martindemello@yahoo.com)]  
> Sent: October 20, 2002 19:52  
> To: ruby-talk ML  
> Subject: Grouping by twos
> 
> Another of those trivial little problems that I obsess about finding  
> the Proper way to do - what’s a nice, idiomatic Ruby way to go from  
> [a,b,c,d…] to [[a,b],[c,d],[e,f],…]? Note that I want to  
> preserve the ordering, so to\_hash won’t work.
> 
> One way I thought of was  
> b = []  
> while a[0] do  
> b \<\< [a.shift, a.shift]  
> end
> 
> which works but doesn’t look particularly elegant.
> 
> martin

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [21 October 2002 20:34 UTC](https://rubytalk.org/t/grouping-by-twos/2388/4 "2002-10-21T20:34:47Z")

</div>

“Allen Mitchell” [ajm@nb.sympatico.ca](mailto:ajm@nb.sympatico.ca) wrote in message news:[MHEFIIKIPJCFBKBGMHOGEEPPCOAA.ajm@nb.sympatico.ca](mailto:MHEFIIKIPJCFBKBGMHOGEEPPCOAA.ajm@nb.sympatico.ca)…

> I ran into the same requirement and I solved it by extending the Array  
> class. Have a look…

Neat. Getting positively verbose, but here’s an extension to Enumerable

module Enumerable  
def eachn(n)  
a =   
if block\_given?  
each {|i|  
a \<\< i  
if a.length == n  
yield a  
a =   
end  
}   
yield a unless a.empty? #possibly padded with nils  
else  
b =   
eachn(n) {|i| b \<\< i}  
b  
end  
end  
end

a = (1…10).to\_a  
b = a.eachn(2)  
puts a.inspect, # =\> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
b.inspect # =\> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]

---

<div class="post-metadata">

**Author:** ![Massimiliano\_Mirra4](https://avatars.discourse-cdn.com/v4/letter/m/43a26b/32.png) [@Massimiliano\_Mirra4](https://rubytalk.org/u/Massimiliano_Mirra4)\
**Post date:** [23 October 2002 09:14 UTC](https://rubytalk.org/t/grouping-by-twos/2388/5 "2002-10-23T09:14:10Z")

</div>

But the method name is short and expressive. I like that. 🙂

Hm, from `eachn’ I’d expect:

a.eachn(2) do |x, y|  
…  
end

a.eachn(3) do |x, y, z|  
…  
end

I’d rewrite `b = a.eachn(2)’ in:

b = a.collectn(2) {|a, b| [a, b]}

For which an optional blockless form would make sense:

b = a.collectn(2)

Massimiliano

> **···**
>
> On Tue, Oct 22, 2002 at 05:34:47AM +0900, Martin DeMello wrote:
> 
> > Neat. Getting positively verbose,
