Forum: Ruby on Rails sorting an array by mutliple fields

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Scott K. (Guest)
on 2009-01-30 01:19
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!
Scott K. (Guest)
on 2009-01-30 02:33
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
Rob B. (Guest)
on 2009-01-30 15:35
(Received via mailing list)
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
removed_email_address@domain.invalid
khoward (Guest)
on 2009-01-30 15:46
(Received via mailing list)
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>
This topic is locked and can not be replied to.