首页 > 解决方案 > 如何使用相同的键对嵌套哈希和数组中的值进行分组和添加?

问题描述

我试图在哈希和数组的组合中获得每个学生的分数总和和平均成绩,但我所有的尝试只返回所有条目的总和。有任何想法吗?

student_data = 
  {"ST4"=>[{:student_id=>"ST4", :points=> 5, :grade=>5}, 
           {:student_id=>"ST4", :points=>10, :grade=>4}, 
           {:student_id=>"ST4", :points=>20, :grade=>5}], 
   "ST1"=>[{:student_id=>"ST1", :points=>10, :grade=>3}, 
           {:student_id=>"ST1", :points=>30, :grade=>4}, 
           {:student_id=>"ST1", :points=>45, :grade=>2}], 
   "ST2"=>[{:student_id=>"ST2", :points=>25, :grade=>5}, 
           {:student_id=>"ST2", :points=>15, :grade=>1}, 
           {:student_id=>"ST2", :points=>35, :grade=>3}], 
   "ST3"=>[{:student_id=>"ST3", :points=> 5, :grade=>5}, 
           {:student_id=>"ST3", :points=>50, :grade=>2}]}

标签: arraysrubyhash

解决方案


这样就可以得到想要的散列。

student_data.transform_values do |arr|
  points, grades = arr.map { |h| h.values_at(:points, :grade) }.transpose
  { :points=>points.sum, :grades=>grades.sum.fdiv(grades.size) }
end
  #=> {"ST4"=>{:points=>35, :grades=>4.666666666666667},
  #    "ST1"=>{:points=>85, :grades=>3.0},
  #    "ST2"=>{:points=>75, :grades=>3.0},
  #    "ST3"=>{:points=>55, :grades=>3.5}} 

传递给块的第一个值是第一个键的值,'ST4'块变量arr被赋予该值:

a = student_data.first
  #=> ["ST4",
  #    [{:student_id=>"ST4", :points=> 5, :grade=>5},
  #     {:student_id=>"ST4", :points=>10, :grade=>4},
  #     {:student_id=>"ST4", :points=>20, :grade=>5}]
  #   ] 
arr = a.last
  #=> [{:student_id=>"ST4", :points=> 5, :grade=>5},
  #    {:student_id=>"ST4", :points=>10, :grade=>4},
  #    {:student_id=>"ST4", :points=>20, :grade=>5}]

块计算如下。arr传递map给内部块的第一个值是

h = arr.first
  #=> {:student_id=>"ST4", :points=>5, :grade=>5} 
h.values_at(:points, :grade)
  #=> [5, 5] 

在剩下的两个元素arr被传递到我们有的块之后

b = arr.map { |h| h.values_at(:points, :grade) }
  #=> [[5, 5], [10, 4], [20, 5]] 

然后

points, grades = b.transpose
  #=> [[5, 10, 20], [5, 4, 5]] 
points
  #=> [5, 10, 20] 
grades
  #=> [5, 4, 5] 

我们现在简单地形成作为 的值的散列'ST4'

c = points.sum
  #=> 35 
d = grades.sum
  #=> 14 
e = grades.size
  #=> 3 
f = c.fdiv(d)
  #=> 4.666666666666667 

'ST4'因此in的值student_data映射到哈希

{ :points=>c, :grades=>f }
  #=> {:points=>35, :grades=>4.666666666666667} 

的其余键的映射以student_data类似方式计算。

参见Hash#transform_valuesEnumerable#mapHash#values_atArray#transposeArray#sumInteger#fdiv


推荐阅读