上下文
尝试在db表中为每个created_at
天生成一个包含1个元素的数组。每个元素是points
天的记录中created_at
(整数)列的平均值。
稍后将绘制图表,以显示每天的平均点数。
结果: 我已经成功地做到了这一点,但感觉就像生成所需结果的代码量不必要。
代码:
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
问题,所以我想知道是否有一个已知的可重复模式来解决这样的问题?
或者更优化的方法来解决这个问题?
(我只是一个初级开发人员,所以你能分享的任何建议都会受到赞赏!)
答案 0 :(得分: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中执行此操作更快(并且还包括更少的代码)。正如您现在所做的那样。
答案 1 :(得分: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
计算平均值。
答案 2 :(得分:-1)