# Sorting an array by mutliple fields

**URL:** <https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982>\
**Category:** Rails\
**Created:** [January 30, 2009, 12:19am UTC](https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982 "2009-01-30T00:19:54Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![skirkpatrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/73ab20/32.png) [@skirkpatrick](https://www.ruby-forum.com/u/skirkpatrick)\
**Post date:** [January 30, 2009, 12:19am UTC](https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982/1 "2009-01-30T00:19:54Z")

</div>

I can do sorting by a single field like the following:

@users.sort! { |a,b| a.name.downcase \< =\> b.name.downcase }

but what if i want to sort by user.name and then user.rank?

what’s the best way to do this?

thanks!

---

<div class="post-metadata">

**Author:** ![skirkpatrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/73ab20/32.png) [@skirkpatrick](https://www.ruby-forum.com/u/skirkpatrick)\
**Post date:** [January 30, 2009, 1:33am UTC](https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982/2 "2009-01-30T01:33:22Z")

</div>

Scott K. wrote:

> I can do sorting by a single field like the following:
> 
> @users.sort! { |a,b| a.name.downcase \< =\> b.name.downcase }
> 
> but what if i want to sort by user.name and then user.rank?
> 
> what’s the best way to do this?
> 
> thanks!

just got it:

@objects.sort! do |a,b|  
comp = (b.rank \<=\> a.rank)  
comp.zero? ? (b.position \<=\> a.position) : comp  
end

in case anyone else needs help

---

<div class="post-metadata">

**Author:** ![skirkpatrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/73ab20/32.png) [@skirkpatrick](https://www.ruby-forum.com/u/skirkpatrick)\
**Post date:** [January 30, 2009, 2:35pm UTC](https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982/3 "2009-01-30T14:35:59Z")

</div>

On Jan 29, 2009, at 7:33 PM, Scott K. wrote:

> just got it:
> 
> @objects.sort! do |a,b|  
> comp = (b.rank \<=\> a.rank)  
> comp.zero? ? (b.position \<=\> a.position) : comp  
> end
> 
> in case anyone else needs help

Actually, you can simplify that a bit:

@objects.sort! do |a,b|  
(b.rank \<=\> a.rank).nonzero? || b.position \<=\> a.position  
end

Look at the docs for Numeric#nonzero?

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![skirkpatrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/73ab20/32.png) [@skirkpatrick](https://www.ruby-forum.com/u/skirkpatrick)\
**Post date:** [January 30, 2009, 2:46pm UTC](https://www.ruby-forum.com/t/sorting-an-array-by-mutliple-fields/158982/4 "2009-01-30T14:46:32Z")

</div>

I haven’t tested this code but basically you want to only sort by  
name, until a.name and b.name are equal. Then you don’t want to sort  
by that. In that CASE you want to sort by a.rank and b.rank.

Something like this…

your\_array\_you\_want\_to\_sort.sort!(&name\_and\_rank\_sort\_method)

```
name_and_rank_sort_method = lambda do |a, b|
  name_compare = a.program.name.downcase <=>

```

b.program.name.downcase #=\> -1, 0. or 1  
rank\_compare = a.rank \<=\> b.name #=\> -1, 0, or 1

```
  if name_compare == 0 #=> e.g., only sort by rank if name is

```

equal  
return rank\_compare #=\> returning -1, 0, or 1  
else  
name\_compare #=\> returning -1, 0, or 1… sorting by name  
because they are not equal.  
end

You can do extremely complex sorting inside of the block… but the  
key to remember is that the block is just returning -1, 0, or 1 based  
on if A is LESS THAN(-1), EQUAL TO(0), or GREATER THAN B (1). So  
regardless of how complex the sort logic is inside, the output is just  
the output of the spaceship operator (\<=\>) (-1, 0, 1). That is all  
Array.sort is expecting…

On Jan 29, 6:19 pm, Scott K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
