基于密钥合并哈希数组中的哈希值 [英] Merging hash values in an array of hashes based on key
问题描述
我有一系列类似于以下的哈希值:
I have an array of hashes similar to this:
[
{"student": "a","scores": [{"subject": "math","quantity": 10},{"subject": "english", "quantity": 5}]},
{"student": "b", "scores": [{"subject": "math","quantity": 1 }, {"subject": "english","quantity": 2 } ]},
{"student": "a", "scores": [ { "subject": "math", "quantity": 2},{"subject": "science", "quantity": 5 } ] }
]
是否有一种更简单的方法来获得类似于此的输出,除了遍历数组并查找重复项然后将它们组合?
Is there a simpler way of getting the output similar to this except looping through the array and finding a duplicate and then combining them?
[
{"student": "a","scores": [{"subject": "math","quantity": 12},{"subject": "english", "quantity": 5},{"subject": "science", "quantity": 5 } ]},
{"student": "b", "scores": [{"subject": "math","quantity": 1 }, {"subject": "english","quantity": 2 } ]}
]
合并重复对象的规则:
- 学生在匹配的值"上合并(例如,学生"a",学生"b")
- 相加相同学科的学生分数(例如,学生a的数学分数2和10合并后变为12)
推荐答案
是否有一种更简单的方法来获得类似于此的输出,除了遍历数组并查找重复项然后将它们组合?
Is there a simpler way of getting the output similar to this except looping through the array and finding a duplicate and then combining them?
我不知道.如果您解释这些数据来自何处,答案可能会有所不同,但仅基于Hash
对象的Array
,我想您会进行迭代和组合.
Not that I know of. IF you explain where this data is comeing form the answer may be different but just based on the Array
of Hash
objects I think you will haev to iterate and combine.
虽然不优雅,您可以使用这样的解决方案
While it is not elegant you could use a solution like this
arr = [
{"student"=> "a","scores"=> [{"subject"=> "math","quantity"=> 10},{"subject"=> "english", "quantity"=> 5}]},
{"student"=> "b", "scores"=> [{"subject"=> "math","quantity"=> 1 }, {"subject"=> "english","quantity"=> 2 } ]},
{"student"=> "a", "scores"=> [ { "subject"=> "math", "quantity"=> 2},{"subject"=> "science", "quantity"=> 5 } ] }
]
#Group the array by student
arr.group_by{|student| student["student"]}.map do |student_name,student_values|
{"student" => student_name,
#combine all the scores and group by subject
"scores" => student_values.map{|student| student["scores"]}.flatten.group_by{|score| score["subject"]}.map do |subject,subject_values|
{"subject" => subject,
#combine all the quantities into an array and reduce using `+`
"quantity" => subject_values.map{|h| h["quantity"]}.reduce(:+)
}
end
}
end
#=> [
{"student"=>"a", "scores"=>[
{"subject"=>"math", "quantity"=>12},
{"subject"=>"english", "quantity"=>5},
{"subject"=>"science", "quantity"=>5}]},
{"student"=>"b", "scores"=>[
{"subject"=>"math", "quantity"=>1},
{"subject"=>"english", "quantity"=>2}]}
]
我知道您指定了预期的结果,但我想指出的是,使输出更简单使代码更简单.
I know that you specified your expected result but I wanted to point out that making the output simpler makes the code simpler.
arr.map(&:dup).group_by{|a| a.delete("student")}.each_with_object({}) do |(student, scores),record|
record[student] = scores.map(&:values).flatten.map(&:values).each_with_object(Hash.new(0)) do |(subject,score),obj|
obj[subject] += score
obj
end
record
end
#=>{"a"=>{"math"=>12, "english"=>5, "science"=>5}, "b"=>{"math"=>1, "english"=>2}}
有了这种结构,吸引学生就像调用.keys
一样容易,并且分数也一样简单.我在想类似
With this structure getting the students is as easy as calling .keys
and the scores would be equally as simple. I am thinking something like
above_result.each do |student,scores|
puts student
scores.each do |subject,score|
puts " #{subject.capitalize}: #{score}"
end
end
end
输出的控制台将是
a
Math: 12
English: 5
Science: 5
b
Math: 1
English: 2
这篇关于基于密钥合并哈希数组中的哈希值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!