我在数据属性中有这个数组数组,每个活动对应一个小时的课堂出勤率。
我需要按小时计算每项活动的总出勤率。 有可能对它进行分组和总结吗?
实施例: 小时7的正确结果是50 + 60 = 110
[{:name=>"cardio",
:data=>[["06", 999], ["07", 50], ["08", 0], ["09", 154], ["10", 1059], ["11", 90], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]},
:name=>"swimming",
:data=>[["06", 0], ["07", 60], ["08", 0], ["09", 0], ["10", 90], ["11", 50], ["12", 0], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]}]
预期结果:
:data=>[["06", 999], ["07", 110], ["08", 0], ["09", 154], ["10", 1149], ["11", 140], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]
答案 0 :(得分:3)
案例1::data
的值是相同大小的数组,其元素(双元素数组)按其第一个元素排序相同
arr = [{ :name=>"cardio", :data=>[["06", 999], ["07", 50], ["08", 0]] },
{ :name=>"swimming", :data=>[["06", 0], ["07", 60], ["08", 0]] }]
a, b = arr.map { |h| h[:data].transpose }.transpose
#=> [[["06", "07", "08"], ["06", "07", "08"]], [[999, 50, 0], [0, 60, 0]]]
{ :data=>a.first.zip(b.transpose.map { |col| col.reduce(:+) }) }
#=> {:data=>[["06", 999], ["07", 110], ["08", 0]]}
案例2::data
的值是可能大小不同的数组,其元素(双元素数组)的第一个元素可能不是相同的
arr = [{ :name=>"cardio", :data=>[["05", 999], ["07", 50], ["08", 0]] },
{ :name=>"swimming", :data=>[["08", 300], ["04", 33], ["07", 60]] }]
{ :data=>arr.flat_map { |g| g[:data] }.
each_with_object(Hash.new(0)) { |(f,v),h| h[f] += v }.
sort.
to_a }
#=> {:data=>[["04", 33], ["05", 999], ["07", 110], ["08", 300]]}
注意:
sort
:data
的值是否并行定义答案 1 :(得分:1)
如何对具有相同结构的数组数组中的值进行分组和求和
你应该这样做:
[{:name=>"cardio",
:data=>[["06", 999], ["07", 50], ["08", 0], ["09", 154], ["10", 1059], ["11", 90], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]},
:name=>"swimming",
:data=>[["06", 0], ["07", 60], ["08", 0], ["09", 0], ["10", 90], ["11", 50], ["12", 0], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]}]
试试这个:
act.map{|h| h[:data]}.flatten(1).group_by(&:first).map { |k,v| [k, v.map(&:last).inject(:+)] }
# => [["06", 999], ["07", 110], ["08", 0], ["09", 154], ["10", 1149], ["11", 140], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]
希望这会对你有所帮助
答案 2 :(得分:1)
假设:
act=[{:name=>"cardio",
:data=>[["06", 999], ["07", 50], ["08", 0], ["09", 154], ["10", 1059], ["11", 90], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]},
{:name=>"swimming",
:data=>[["06", 0], ["07", 60], ["08", 0], ["09", 0], ["10", 90], ["11", 50], ["12", 0], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]}]
你可以这样做:
> act.map{ |h| h[:data] }
.flatten(1)
.group_by{ |h,n| h }
.map { |k,v| [k, v.map(&:last).sum] }
=> [["06", 999], ["07", 110], ["08", 0], ["09", 154], ["10", 1149], ["11", 140], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]
或者,
> act.map{|h| h[:data]}
.flatten(1)
.each_with_object(Hash.new(0)) {|e,h| h[e[0]]+=e[1]}.to_a
也有效。
答案 3 :(得分:0)
actions=[{:name=>"cardio",
:data=>[["06", 999], ["07", 50], ["08", 0], ["09", 154], ["10", 1059], ["11", 90], ["12", 30], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]},
{:name=>"swimming",
:data=>[["06", 0], ["07", 60], ["08", 0], ["09", 0], ["10", 90], ["11", 50], ["12", 0], ["13", 0], ["14", 0], ["15", 0], ["16", 0], ["17", 0], ["18", 0], ["19", 0], ["20", 0], ["21", 0], ["22", 0], ["23", 0]]}]
actions.map{|act| act[:data]}.reduce({}) do |acc, data|
acc.merge(data.to_h) {|k, v1, v2| v1 + v2}
end.to_a
此解决方案利用了Ruby' Hash
保持插入顺序的事实。
该算法的优点在于它允许在任一数据阵列中丢失密钥。