Ruby:比较两个匹配的数组,并按DESC顺序排序结果

时间:2011-02-18 03:15:00

标签: ruby-on-rails ruby

我有一个用户模型。每个用户都有与之关联的餐馆名称。我有一个显示所有用户的视图(index.html.erb)。

我想根据current_user和其他一些用户有多少餐厅按降序排序,在这个视图中订购用户......(反之亦然!)


离。

User1(current_user)去过麦当劳,汉堡王,阿比的

User2去过Ivar的

User3去过麦当劳,汉堡王


当User1加载索引视图时,用户应显示的顺序为:

User1(3/3餐厅匹配)

User3(2/3餐厅匹配)

User2(0/3餐厅匹配)


我的User.rb文件

def compare_restaurants
  self.restaurants.collect
end

my users_controller.rb

def index
  @users = User.all.sort_by {|el| (el.compare_resturants & current_user.compare_resturants).length }
end

2 个答案:

答案 0 :(得分:4)

如果您已经开始使用sort_by,那么您可以忽略这些数字:

def index
  @users = User.all.sort_by { |el|
    -(el.compare_resturants & current_user.compare_resturants).length
  }
end

此技巧仅适用,因为您按数值排序。如果你在字符串上排序,那么你必须使用这样的东西:

reverse_sorted = a.sort_by { |x| something(x) }.reverse

但这将涉及数组的额外副本以及reverse将要执行的额外工作。在这种情况下,您应该使用带有反向比较逻辑的完整sort

如果你正在尝试使用sort_by来避免为每次比较计算昂贵的东西而你正在对非数字的东西进行排序,那么你总是可以sort使用明确的Schwartzian Transform只计算一次昂贵的东西。

答案 1 :(得分:0)

只需在控制器中对它们进行排序即可。

my = User.find_by_id this_user  # Or however you're getting "the current user"
@users = User.all.-([my]).sort do |a, b|
  common_with_a = (my.restaurants & a.restaurants).length
  common_with_b = (my.restaurants & b.restaurants).length
  common_with_a <=> common_with_b
end

...但是如果您计划让用户开始对各个列进行排序或者对排序进行大量反转,那么您应该在Javascript中实现排序,这样您就可以减少页面重新加载的次数以及随后的数据库命中率不得不做。