基于密钥合并哈希数组中的哈希值 [英] Merging hash values in an array of hashes based on key

查看:69
本文介绍了基于密钥合并哈希数组中的哈希值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一系列类似于以下的哈希值:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆