我有一个包含值和数组的数组,如下所示:
arr = [
[ 0, [ [22,3],[23,5] ] ],
[ 0, [ [22,1],[23,2] ] ],
[ 1, [ [22,4],[23,4] ] ],
[ 1, [ [22,2],[23,4] ] ]
]
我想根据前两个元素计算平均值,并希望在哈希或数组中得到一个结果集,如下所示:
result = {
22 => [(3+1)/2, (4+2)/2],
23 => [(5+2)/2, (4+4)/2]
}
例如:
键是 22 ,值是一个数组,包含按第一个元素 3和1,4分组的输入数组中第三个元素的平均值和2 并按第一个元素 0和1
排序提及我的逻辑可能会有所帮助。
通过以下代码从我的ActiveRecord对象中获取数组:
arr = u.feedbacks.map{|f| [f.week,
f.answers.map{|a| [a.question.id, a.name.to_i]}]}
模型的关联方式如下:
feedback belongs_to :user
feedback has_and_belongs_to_many :answers
answer belongs_to :question
对于每个问题,我想创建一个包含按反馈周分组的平均答案的数组。
答案 0 :(得分:2)
通过一些调试,以下内容应该有助于获得更快的结果:
Answer.
joins(:question, :feedbacks). # assuming that answer has_many feedbacks
group(["questions.id", "feedbacks.week"]). # assuming week is integer column
average("CAST(answers.name AS INT)"). # assuming that name is string-y column
each_with_object({}) do |(keys, average), hash|
question_id, week = keys
hash[question_id] ||= []
hash[question_id][week] = average
end
如果你想保持原样(不建议),那么一个工作(虽然难以理解)的解决方案就是:
arr = [
[0, [[22, 3], [23, 5]]],
[0, [[22, 1], [23, 2]]],
[1, [[22, 4], [23, 4]]],
[1, [[22, 2], [23, 4]]]
]
arr.each_with_object({}) do |(a, b), hash|
c, d, e, f = b.flatten
# for first row this will be c, d, e, f = 22, 3, 23, 5
hash[c] ||= []
hash[c][a] ||= []
hash[c][a] << d
hash[e] ||= []
hash[e][a] ||= []
hash[e][a] << f
end.each_with_object({}) do |(k, v), hash|
# k are your 'keys' like 22, 23
# v is an array of arrays that you want to find out the averages of
hash[k] = \
v.map do |array|
array.reduce(:+).fdiv(array.size)
end
end
答案 1 :(得分:1)
如果是我,我可以按照自己的方式行事,那么我将重构arr
从第一个位置创建的方式,因为
但是我没有比你从所展示的代码中看到的更多的见解。所以,我玩了一下,也许下面的代码是你想要的?
totals = {}
arr.each do |row|
index, answers = row
answers.each do |answer|
question, count = answer
totals[question] ||= []
totals[question][index] ||= []
totals[question][index] << count
end
end
以下是totals
的输出,到那时为了获得平均值,这是微不足道的。
{
22 =>[[3, 1], [4, 2]],
23=>[[5, 2], [4, 4]]
}
编辑以下是我使用each_with_object
解决的解决方案,我从@Humza那里学到了
arr = [
[ 0, [ [22,3],[23,5] ] ],
[ 0, [ [22,1],[23,2] ] ],
[ 1, [ [22,4],[23,4] ] ],
[ 1, [ [22,2],[23,4] ] ]
]
result = arr.each_with_object({}) do |(index, feedbacks), totals|
feedbacks.each do |(question, count)|
totals[question] ||= {}
totals[question][index] ||= []
totals[question][index] << count
end
totals
end.each_with_object({}) do |(question, totals), result|
result[question] = totals.map do |(index, total)|
total.reduce(:+).fdiv(total.length)
end
end
puts result.inspect
## Output
# {22=>[2.0, 3.0], 23=>[3.5, 4.0]}