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.
Debcfd8f3f533800e2711c704825f9c0?d=identicon&s=25 Scott Kulik (kuliksco)
on 2009-01-30 00: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!
Debcfd8f3f533800e2711c704825f9c0?d=identicon&s=25 Scott Kulik (kuliksco)
on 2009-01-30 01:33
Scott Kulik 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
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-01-30 14:35
(Received via mailing list)
On Jan 29, 2009, at 7:33 PM, Scott Kulik 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 Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
0405404a04cff720c0133c410e3825a6?d=identicon&s=25 khoward (Guest)
on 2009-01-30 14: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 Kulik <rails-mailing-l...@andreas-s.net>
This topic is locked and can not be replied to.