Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort an array in Ruby ignoring articles ("the", "a", "an")

In my application I need to show a list of songs. Right now I'm doing this:

Song.all.sort {|x,y| x.artist.name <=> y.artist.name }

Unfortunately, this means that "The Notorious B.I.G" will sort with the T's while I want him to sort with the N's (i.e., I want to ignore articles -- "the", "a", and "an" -- for the purposes of sorting.

My first thought was to do this:

Song.all.sort {|x,y| x.artist.name.gsub(/^(the|a|an) /i, '') <=> y.artist.name.gsub(/^(the|a|an) /i, '') }

But it doesn't seem to work. Thoughts?

like image 282
Tom Lehman Avatar asked Dec 17 '22 06:12

Tom Lehman


1 Answers

My favorite approach to these kind of problems is to store an extra sort_order column in the database.

That way when you have 10000 songs that you would like to page through, you can do that in SQL and avoid having to pull them all back.

Its simple to add a before_save filter to keep this column in sync.

The cleanish solution, without schema changes is:

class Artist
  def sortable_name
    self.name.sub(/^(the|a|an)\s+/i, '')
  end
end

class Song
  def sortable_name
    # note the - is there so [Radio] [head on] and [Radiohead] [karma police] 
    #   are not mixed in the ordering
    "#{artist.sortable_name} - #{name}" 
  end
end

# breaks ties as well 
Song.all.sort_by { |song| song.sortable_name }
like image 81
Sam Saffron Avatar answered Dec 31 '22 02:12

Sam Saffron