如何获得一个项目在ActiveRecord集合中的排名?有关系吗?

时间:2016-12-18 03:08:57

标签: ruby-on-rails ruby activerecord

我收到了@players的集合,按total_points排序。我试图找出特定的@player在@players集合中排名的位置。

示例:有5个玩家,这是他们的total_points:

  • 球员1:20分
  • 球员2:20分
  • 球员3:15分
  • 球员4:15分
  • 球员5:15分

鉴于我们衡量这样的关系:

  • 玩家1:并列第1名
  • 玩家2:争夺第一名
  • 玩家3:并列第3名
  • 玩家4:并列第3名
  • 玩家5:并列第3名

显示玩家4等级的最简单方法是什么?这可能没有遍历整个集合吗?我知道如何通过检查以前的迭代器的total_score是否相同来打印整个列表,但我不需要显示整个列表,只显示当前玩家的等级。

在我的应用程序中,将会有近千名玩家,所以我试图找到一种快速计算的方法。

编辑:

根据@ max的答案,我在此提出了什么:

 @grouped_players = Player.all.reorder(total_points: :desc).group(:total_points).count
 our_rank = 0
 tied = false
 @grouped_players.each do |points, count|
   if points > @player.total_points
     our_rank += count
   end
   if points == @player.total_points
     our_rank += 1
     if count > 1
       tied = true
     end
     break
   end
 end

 puts our_rank
 puts tied

任何人都有更优雅的解决方案吗?

2 个答案:

答案 0 :(得分:2)

你基本上试图找出有多少玩家得分高于当前玩家的得分,然后加1.如果total_points是数据库属性,你应该可以打电话Player.group(:total_points).count,在您的示例中应返回{ 20 => 2, 15 => 3 }。然后,您选择散列中哪些元素的键大于当前玩家的分数,将值相加,然后添加1.如果您愿意,可以在数据库中执行该过程的某些部分而不是Ruby;如果你有很多不同的分数可能会更有效率(因此返回的哈希值非常大)。但是有1000名玩家,除非你频繁地进行计算,否则我认为这不是一个大问题。

答案 1 :(得分:0)

您可以使用Active Record group方法执行此操作,如下所示。 让您拥有Player模型,其中point列将用于衡量排名。所以,查询就像

Player.where(point: Player.group(:point).sort[3])

您可以看到group 4th返回数组。我们正在排序以确保4th位置将在索引3上。现在使用第4个位置点来搜索所有用户。请注意,如果数据上没有null位置,则会搜索具有0值的用户。因此,请确保每个用户的点数至少为mean_by_zip = sales.groupby(key_columns=['zipcode'], operations={'avg': graphlab.aggregate.MEAN('price')}) mean_by_zip.sort('avg', ascending=False)[0:3] # will give top 3 。希望它会对你有所帮助。