# Grouping array elements while preserving order?

**URL:** <https://www.ruby-forum.com/t/grouping-array-elements-while-preserving-order/149123>\
**Category:** Ruby\
**Created:** [September 20, 2008, 11:55pm UTC](https://www.ruby-forum.com/t/grouping-array-elements-while-preserving-order/149123 "2008-09-20T23:55:24Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![mattclarkson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/958977/32.png) [@mattclarkson](https://www.ruby-forum.com/u/mattclarkson)\
**Post date:** [September 20, 2008, 11:55pm UTC](https://www.ruby-forum.com/t/grouping-array-elements-while-preserving-order/149123/1 "2008-09-20T23:55:24Z")

</div>

Hi all,

I’ve run into a number of situations where I need to group an array  
while preserving order. For example, grouping the results of a database  
query without affecting their order or introducing extraneous logic in a  
view.

I would like to know if there are any obvious problems or improvements  
to this solution:

class Array  
def partition\_by(&b)  
out=[]  
self.inject([]) {|acc,e|  
last = acc.pop  
value = b.call(e)  
out \<\< {value=\>[]} if last != value  
out.last[value] \<\< e  
acc \<\< value  
}  
out  
end  
end

So if I partition an array by element length, for example (contrived, I  
know):  
animals = %w(dog dog cat chicken chicken dog)  
animals.partition\_by{|x| x.length}

I get:  
[{3=\>[“dog”, “dog”, “cat”]}, {7=\>[“chicken”, “chicken”]}, {3=\>[“dog”]}]

Any thoughts or suggestions?

- Matt

---

<div class="post-metadata">

**Author:** ![mattclarkson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/958977/32.png) [@mattclarkson](https://www.ruby-forum.com/u/mattclarkson)\
**Post date:** [September 21, 2008, 3:52am UTC](https://www.ruby-forum.com/t/grouping-array-elements-while-preserving-order/149123/2 "2008-09-21T03:52:09Z")

</div>

On Sep 20, 4:47 pm, Matt C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class Array  
> end  
> end
> 
> So if I partition an array by element length, for example (contrived, I  
> know):  
> animals = %w(dog dog cat chicken chicken dog)  
> animals.partition\_by{|x| x.length}
> 
> I get:  
> [{3=\>[“dog”, “dog”, “cat”]}, {7=\>[“chicken”, “chicken”]}, {3=\>[“dog”]}]

Without hashes:

class Array  
def group\_by  
key = nil  
inject([]){|result,x|  
k = yield x  
if key == k and result != []  
result[-1] \<\< x  
next result  
end  
key = k  
result \<\< [x]  
}  
end  
end

---

<div class="post-metadata">

**Author:** ![mattclarkson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/958977/32.png) [@mattclarkson](https://www.ruby-forum.com/u/mattclarkson)\
**Post date:** [September 22, 2008, 7:30am UTC](https://www.ruby-forum.com/t/grouping-array-elements-while-preserving-order/149123/3 "2008-09-22T07:30:42Z")

</div>

On 21.09.2008 03:22, William J. wrote:

> > ```
> > out
> > 
> > ```
> 
> ```
> end
> key = k
> result << [x]
> }
> 
> ```
> 
> end  
> end

You’re loosing keys there. Maybe rather

module Enumerable  
def group\_by\_ordered  
inject([]) do |agg, v|  
k = yield v  
if agg.empty? || k != agg.last.first  
agg \<\< [k, [v]]  
else  
agg.last.last \<\< v  
end  
agg  
end  
end  
end

irb(main):014:0\> animals = %w(dog dog cat chicken chicken dog)  
=\> [“dog”, “dog”, “cat”, “chicken”, “chicken”, “dog”]  
irb(main):015:0\> animals.group\_by\_ordered {|x| x.length}  
=\> [[3, [“dog”, “dog”, “cat”]], [7, [“chicken”, “chicken”]], [3,  
[“dog”]]]  
irb(main):016:0\>

Cheers

robert
