# Sort an array based on an attribute of its objects

**URL:** <https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103>\
**Category:** Ruby\
**Created:** [August 28, 2008, 1:44pm UTC](https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103 "2008-08-28T13:44:14Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [August 28, 2008, 1:44pm UTC](https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103/1 "2008-08-28T13:44:14Z")

</div>

Hi all

The title of this topic is not very good, but I didn’t really know how  
to describe it in just a few words…

So here is what I need to do:

I have a array of some objects:

[obj1, obj2, obj3, obj4]

All objects have a method “status” that returns a status object, like  
“open”, “request”, “cancelled”, “completed” etc.

Now I’d like to sort the elements after theses statuses into a new hash,  
so in the end it should look something like this:

{status1 =\> [obj1, obj3],  
status3 =\> [obj2],  
status4 =\> [obj4]}

I need this because I want then to iterate through the hash and display  
an HTML list grouped by status:

- Request: 
  - Object 1
  - Object 3

- Cancelled: 
  - Object 2

 ... and so on...

What’s an elegant way to do this? 🙂

Thanks a lot,  
Josh

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [August 28, 2008, 2:04pm UTC](https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103/2 "2008-08-28T14:04:31Z")

</div>

Hi –

On Thu, 28 Aug 2008, Joshua M. wrote:

> I need this because I want then to iterate through the hash and display
> 
> - Cancelled: 
> - Object 2
> 
> ... and so on...
> 
> What’s an elegant way to do this? 🙂

In Ruby 1.9 you can do:

array.group\_by {|obj| obj.status }

and get a hash. If you need to roll your own:

class Array  
def group\_by  
hash = Hash.new {|h,k| h[k] = [] }  
each {|e| hash[yield(e)] \<\< e }  
hash  
end  
end

(or in a module, or whatever).

David

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [August 28, 2008, 2:16pm UTC](https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103/3 "2008-08-28T14:16:53Z")

</div>

On Thu, Aug 28, 2008 at 1:58 PM, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:  
David beat me to the line, but as somebody will post an inject based  
solution anyway, why not let it be me ;).

class Array  
def group\_by message = nil  
inject( Hash.new {|h,k| h[k] = [] } ){ |h, e|  
h[message ? e.send( message ) : yield(e)] \<\< e  
h  
}  
end  
end

p %w{ Hello Brave GNU World }.group\_by {|o| o.size }  
p %w{ Hello Brave GNU World }.group\_by( :size )

Cheers  
Robert

–  
[http://ruby-smalltalk.blogspot.com/](http://ruby-smalltalk.blogspot.com/)

There’s no one thing that’s true. It’s all true.

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [August 28, 2008, 2:19pm UTC](https://www.ruby-forum.com/t/sort-an-array-based-on-an-attribute-of-its-objects/147103/4 "2008-08-28T14:19:14Z")

</div>

On Thu, Aug 28, 2008 at 1:39 PM, Joshua M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> {status1 =\> [obj1, obj3],  
> status3 =\> [obj2],  
> status4 =\> [obj4]}

If working with a Set is fine (there’s #to\_set) that’s provided by  
Set#classify.
