我如何组和嵌套哈希和数组有相同的键添加值?

问题描述 投票:-1回答:3

我试图让哈希和数组的结合点内为每个学生的总和和平均品位,但我所有的努力只返回一般总和的所有条目。有任何想法吗?

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}]}
arrays ruby hash
3个回答
0
投票

无论你希望可以如下实现,

student_data.values.map do |z|
  z.group_by { |x| x[:student_id] }.transform_values do |v|
    { 
      points: v.map { |x| x[:points] }.sum, # sum of points
      grade: (v.map { |x| x[:grade] }.sum/v.count.to_f).round(2) # average of grades
    }
  end
end

由于未指定确切预期的输出格式,在下面的方式获得,

=> [
  {"ST4"=>{:points=>35, :grade=>4.67}},
  {"ST1"=>{:points=>85, :grade=>3.0}},
  {"ST2"=>{:points=>75, :grade=>3.0}},
  {"ST3"=>{:points=>55, :grade=>3.5}}
]

1
投票

所期望的散列可以正是如此获得。

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] 

我们现在只是从是qazxsw POI值的哈希值。

'ST4'

因此c = points.sum #=> 35 d = grades.sum #=> 14 e = grades.size #=> 3 f = c.fdiv(d) #=> 4.666666666666667 'ST4'的值映射到散列

student_data

{ :points=>c, :grades=>f } #=> {:points=>35, :grades=>4.666666666666667} 的剩余键的映射类似地计算。

见qazxsw POI,qazxsw POI,qazxsw POI,student_dataHash#transform_valuesEnumerable#map


0
投票

为Ruby 2.6使用Hash#values_atArray#transpose为Ruby 2.5

Array#sum


How it works?

鉴于阵列为每个学生:

Integer#fdiv

首先建立一个散列添加和使用Object#thenObject#yield_self组计数为零student_data.transform_values { |st| st .each_with_object(Hash.new(0)) { |h, hh| hh[:sum_points] += h[:points]; hh[:sum_grade] += h[:grade]; hh[:count] += 1.0 } .then{ |hh| {tot_points: hh[:sum_points], avg_grade: hh[:sum_grade]/hh[:count] } } }

st = [{:student_id=>"ST4", :points=> 5, :grade=>5}, {:student_id=>"ST4", :points=>10, :grade=>4}, {:student_id=>"ST4", :points=>20, :grade=>5}]

然后用呢! (Enumerable#each_with_object为Ruby 2.5)

Hash#default

把所有一起使用(Hash.new(0)作为代码的第一个片段

© www.soinside.com 2019 - 2024. All rights reserved.