2016-04-29 46 views
2

上下文: 试图产生与用于每个created_at一天分贝表1个元件的阵列。每个元素是来自created_at天的记录的points(整数)列的平均值。 这将稍后绘制成每天显示点数的平均值。生成从数据库表(Rails)的每日平均值数组

结果: 我已经成功地做到了这一点,但感觉就像不必要的代码量来产生所需的结果。

代码:

def daily_avg 
    # get all data for current user 
    records = current_user.rounds 

    # make array of long dates 
    long_date_array = records.pluck(:created_at) 

    # create array to store short dates 
    short_date_array = [] 

    # remove time of day 
    long_date_array.each do |date| 
     short_date_array << date.strftime('%Y%m%d') 
    end 

    # remove duplicate dates 
    short_date_array.uniq! 

    # array of avg by date 
    array_of_avg_values = [] 

    # iterate through each day 
    short_date_array.each do |date| 
     temp_array = [] 

     # make array of records with this day 
     records.each do |record| 
      if date === record.created_at.strftime('%Y%m%d') 
       temp_array << record.audio_points 
      end 
     end 
     # calc avg by day and append to array_of_avg_values 
     array_of_avg_values << temp_array.inject(0.0) { |sum, el| sum + el }/temp_array.size 
    end 
    render json: array_of_avg_values 
end 

问题: 我觉得这是一个常见的extraction问题需要通过大量的应用程序来解决,所以我不知道是否有解决一个已知的重复模式像这样?

还是更理想的解决方法?

(我几乎没有一个初级开发者,所以你可以分享任何建议,将不胜感激!)

回答

2

是的,这是一个很大的不必要的东西时,你可以去到SQL做到这一点(我假设你在你的应用程序有一个名为Round类):

class Round 

    DAILY_AVERAGE_SELECT = "SELECT 
     DATE(rounds.created_at) AS day_date, 
     AVG(rounds.audio_points) AS audio_points 
    FROM rounds 
    WHERE rounds.user_id = ? 
    GROUP BY DATE(rounds.created_at) 
" 

    def self.daily_average(user_id) 
    connection.select_all(sanitize_sql_array([DAILY_AVERAGE_SELECT, user_id]), "daily-average") 
    end 

end 

做直入本数据库会比现在做的更快(并且包含更少的代码),而不是像Ruby那样。

+0

将created_at转换为刚刚从日期时间约会? –

0

我建议你做这样的事情:

grouped = 
records.order(:created_at).group_by do |r| 
    r.created_at.strftime('%Y%m%d') 
end 

起初在这里你生成正确的SQL接近你希望得到的第一个近似值,然后将created_at字段的结果记录转换成只是一个日期。

points = 
grouped.map do |(date, values)| 
    [ date, values.reduce(0.0, :audio_points)/values.size ] 
end.to_h 

# => { "1-1-1970" => 155.0, ... } 

然后,您通过数组重新映射您的分组散列,以计算audio_points的平均值。