Сортировать массив в Ruby, игнорируя статьи ("the", "a", "an") - PullRequest
4 голосов
/ 10 сентября 2009

В моем приложении мне нужно показать список песен. Прямо сейчас я делаю это:

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

К сожалению, это означает, что «Пресловутый БОЛЬШОЙ» будет сортироваться с Т, в то время как я хочу, чтобы он сортировал с Н (т. Е. Я хочу игнорировать статьи - «,», «и» - - для целей сортировки.

Моей первой мыслью было сделать это:

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

Но, похоже, это не работает. Мысли?

Ответы [ 4 ]

12 голосов
/ 10 сентября 2009

Мой любимый подход к решению подобных проблем - хранить в базе данных столбец extra sort_order.

Таким образом, когда у вас есть 10000 песен, которые вы хотите просмотреть, вы можете сделать это в SQL и избежать необходимости возвращать их обратно.

Добавить фильтр before_save просто, чтобы синхронизировать этот столбец.

Чистое решение без изменений схемы:

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 }
0 голосов
/ 10 сентября 2009

Разбей!

class Artist < ActiveRecord::Base

  def <=>(other)
    name.gsub(/^(the|a|an) /i, '') <=> other.name.gsub(/^(the|a|an) /i, '')
  end

end

songs = Song.all(:include => :artist)
songs.sort_by { |s| s.artist }
0 голосов
/ 10 сентября 2009

Ваш ответ кажется правильным, но, вероятно, вы можете изменить его на:

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

изменено на sub, потому что вам нужно изменить его только в начале, а не на всю строку, пробел изменился на \ s, чтобы указать пробел.

Вы можете перейти на http://www.rubyxp.com/, чтобы проверить свое регулярное выражение

если он все еще не работает, то, возможно, некоторые записи выходят не так, как должны? например, пробелы в начале строки, ноль или пустой заголовок и т. д. *

надеюсь, это поможет =)

0 голосов
/ 10 сентября 2009

Возможно, вам лучше сделать это в SQL,

SELECT Title,
CASE WHEN SUBSTRING_INDEX(Title, ' ', 1)
        IN ('a', 'an', 'the')
    THEN CONCAT(
        SUBSTRING(Title, INSTR(Title, ' ') + 1),
        ', ',
        SUBSTRING_INDEX(Title, ' ', 1)
    )
    ELSE Title
END AS TitleSort
FROM music
ORDER BY TitleSort

Есть статья , которая также описывает это более подробно.

Большим преимуществом по сравнению с изложенным вами подходом является то, что вы сначала вытаскиваете ВСЕ записи, что изощренно портит вас, как с точки зрения производительности, так и с точки зрения пользовательского интерфейса (я думаю о таких ситуациях, как попытка пролистать страницы). через большой набор песен).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...