我正在尝试建立一个网站,对特定事件中的一些运动员的表现进行排名 - 我之前发布了一个问题,该问题得到了一些好的答复,我现在可以通过我的代码找出关键问题。
我有2个模型 - Athlete
和Result
(运动员有很多结果)
每位运动员可以为特定赛事记录一些时间,我想确定每位运动员最快的时间,并将这些最快的时间排在所有运动员之列。
我使用以下代码:
<% @filtered_names = Result.where(:event_name => params[:justevent]).joins(:athlete).order('performance_time_hours ASC').order('performance_time_mins ASC').order('performance_time_secs ASC').order('performance_time_msecs ASC') %>
这成功地对所有运动员的所有结果进行了排名(即一名运动员可以根据他们记录的时间在不同的地方出现多次)。
我现在希望为每位运动员取出最佳成绩,并将其纳入排名。我可以使用以下方法选择与最佳结果相对应的时间:
<% @currentathleteperformance = Result.where(:event_name => params[:justevent]).where(:athlete_id => filtered_name.athlete_id).order('performance_time_hours ASC').order('performance_time_mins ASC').order('performance_time_secs ASC').order('performance_time_msecs ASC').first() %>
但是,当我尝试识别@filtered_names
中列出的不同运动员名字时,我的问题出现了。我尝试使用<% @filtered_names = @filtered_names.select('distinct athlete_id') %>
,但这并不像我预期的那样,有时它会以错误的顺序排名。
我发现,因为它代表我的代码基本上寻找不同的运动员结果之间的差异,从小时时间开始到进展到分钟,秒和毫秒。一旦发现每个不同运动员的结果之间存在差异,它就会相应地命令它们。
例如,如果我有2名运动员:
Time for Athlete 1 = 0:0:10:5
Time for Athlete 2 = 0:0:10:3
这将产生命令,运动员2,运动员1
但是,如果我有:
Time for Athlete 1 = 0:0:10:5
Time for Athlete 2 = 0:0:10:3
Time for Athlete 2 = 0:1:11:5
然后命令为运动员1,运动员2,因为第一个差异在分钟数字,运动员2更慢......
任何人都可以建议一种解决此问题的方法,并且基本上在@filtered_names
中删除第一次出现的每个名称时的条目(即将名称保持在它们首次出现在{{1}中的顺序中}
感谢您的时间
答案 0 :(得分:1)
如果您使用的是Ruby 1.9.2+,则可以使用Array#uniq
并传递一个指定如何确定唯一性的块。例如:
@unique_results = @filtered_names.uniq { |result| result.athlete_id }
每个运动员只能返回一个结果,并且一个结果应该是数组中的第一个结果,这反过来将是您已经订购结果的最快时间。
有一点需要注意:@filtered_names
可能仍然是ActiveRecord::Relation
,它有自己的#uniq
方法。您可能首先需要调用#all
来返回结果数组:
@unique_results = @filtered_names.all.uniq { ... }
答案 1 :(得分:0)
您应该使用DB来执行最大计算,而不是ruby代码。将新列添加到名为results
的{{1}}表中,并在每次更改“结果”表时为其设置值。
total_time_in_msecs
现在您可以按如下方式编写查询:
class Result < ActiveRecord::Base
before_save :init_data
def init_data
self.total_time_in_msecs = performance_time_hours * MSEC_IN_HOUR +
performance_time_mins * MSEC_IN_MIN +
performance_time_secs * MSEC_IN_SEC +
performance_time_msecs
end
MSEC_IN_SEC = 1000
MSEC_IN_MIN = 60 * MSEC_IN_SEC
MSEC_IN_HOUR = 60 * MSEC_IN_MIN
end
写一个简单的助手来分解数字时间部分:
athletes = Athlete.joins(:results).
select("athletes.id,athletes.name,max(results.total_time_in_msecs) best_time").
where("results.event_name = ?", params[:justevent])
group("athletes.id, athletes.name").
orde("best_time DESC")
athletes.first.best_time # prints a number
在视图中使用帮助程序显示细分时间。