0

我想从数据库中的电影中获取评分并返回一组独特的评分,按以下顺序排序:

G PG PG-13 R NC-17

一个平原Array#sort是不够的:

["PG-13", "PG", "NC-17", "G", "R"].sort
# => ["G", "NC-17", "PG", "PG-13", "R"]

下面的代码给了我想要的东西,但似乎有更好的方法来编写它,而不必使用deleteand <<。任何想法,将不胜感激。

class Movie < ActiveRecord::Base
  def self.all_ratings
    allRatings = []
    Movie.all.each do |movie|
      unless allRatings.include?(movie.rating)
        allRatings << movie.rating
      end
    end
    if allRatings.include?("NC-17")
      allRatings.sort!
      allRatings.delete("NC-17")
      allRatings << "NC-17"
      return allRatings
    else
      return allRatings.sort
    end
  end
end

更新:使用 Sergio 的提示,我能够重构代码。如果有人有其他想法,我会很感激反馈。

class Movie < ActiveRecord::Base

  def self.all_ratings
    allRatings = []
    Movie.all.each do |movie|
      unless allRatings.include?(movie.rating)
        allRatings << movie.rating
      end
    end
    allRatings.sort_by! {|t| t == 'NC-17' ? 'ZZZ' : t}
  end
end

更新:使用 ByScripts 提示,此代码运行良好且非常简洁。我必须从 Rails 3.1.0 升级到 Rails 3.2.8 才能获得该pluck方法。看起来它是在 3.2.1 中引入的。

我还必须添加.sort以获得所需的输出。

class Movie < ActiveRecord::Base

  def self.all_ratings
    all_ratings = Movie.pluck(:rating).uniq.sort# don't retrieve unnecessary datas
    all_ratings << all_ratings.delete('NC-17') # directly inject NC-17 at the end if exists
    all_ratings.compact # remove nil values
  end

end
4

4 回答 4

2

你可以使用这个小技巧

sorted = ["PG-13", "PG", "NC-17", "G", "R"].sort_by {|t| t == 'NC-17' ? 'ZZZ' : t }

sorted # => ["G", "PG", "PG-13", "R", "NC-17"]

基本上,出于排序目的,您将“NC-17”替换为最后排序的“ZZZ”。

于 2013-01-28T19:31:12.337 回答
2

那应该有效:

def self.all_ratings
  all_ratings = Movies.order(:rating).pluck(:rating).uniq # don't retrieve unnecessary datas
  all_ratings << all_rating.delete('NC-17') # directly inject NC-17 at the end if exists
  all_ratings.compact # remove nil values
end

你也可以做Movies.uniq.pluck(:rating)

那会做一个SELECT DISTINCT查询(pluck.uniq过滤数组的地方)。不知道是否会对性能产生影响(可能是内存占用较低?)。

无论如何,两者应该是一样的。

于 2013-01-28T20:35:25.693 回答
1

我喜欢 Sergio 的把戏,但如果您正在寻找原始代码的更简单版本,但仍然有deleteand <<,试试这个

def sort(ratings)
  ratings.sort!
  return ratings unless ratings.include?("NC-17")

  ratings.delete("NC-17")

  ratings << "NC-17"
end
于 2013-01-28T19:35:32.397 回答
1
class Movie < ActiveRecord::Base
  RatingOrder = %w[G PG PG-13 R NC-17]
  def self.all_ratings
    RatingOrder & Movie.all.map(&:rating)
  end
end
于 2013-01-31T09:12:14.497 回答