Sorting an array by mutliple fields


#1

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!


#2

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


#3

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


#4

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