Ruby总结字典值的方式

时间:2013-07-12 16:16:47

标签: ruby enumerable

我有这样的事情:

a = [{"group_id" => 1, "student_id" => 3, "candies" => 4},
  {"group_id" => 2, "student_id" => 1, "candies" => 3},
  {"group_id" => 1, "student_id" => 2, "candies" => 2},
  {"group_id" => 3, "student_id" => 4, "candies" => 6},
  {"group_id" => 1, "student_id" => 5, "candies" => 1},
  {"group_id" => 3, "student_id" => 6, "candies" => 1},
  {"group_id" => 4, "student_id" => 8, "candies" => 3}]

我有三组学生,每个学生都有一定数量的糖果。我想计算一组糖果的总数。为此,我需要了解属于某一群体的学生并积累他们的糖果数。我可以使用循环并将计数初始化为零来执行此操作:

aa = a.group_by { |a| a["group_id"] }
# =>
{
  1 => [
    {"group_id"=>1, "student_id"=>3, "candies"=>4},
    {"group_id"=>1, "student_id"=>2, "candies"=>2},
    {"group_id"=>1, "student_id"=>5, "candies"=>1}
  ],
  2 => [{"group_id"=>2, "student_id"=>1, "candies"=>3}],
  3 => [
    {"group_id"=>3, "student_id"=>4, "candies"=>6},
    {"group_id"=>3, "student_id"=>6, "candies"=>1}
  ],
  4 => [{"group_id"=>4, "student_id"=>8, "candies"=>3}]
}

但我无法累积group_id中的值。我想知道是否有任何简洁的方式来代表它。如何计算组中存在的糖果总数?

3 个答案:

答案 0 :(得分:1)

您的第一步(分组)是正确的。之后,您可以使用以下内容:

a.group_by {|g| g['group_id']}.map do |g, students|
  {group_id:g, candies:students.map {|st| st['candies']}.inject(&:+)}
end

map函数通常与集合而不是循环一起使用,以对每个元素进行一些操作并返回集合的修改版本。

<强>输出:

[{:group_id=>1, :candies=>7}, 
 {:group_id=>2, :candies=>3}, 
 {:group_id=>3, :candies=>7}, 
 {:group_id=>4, :candies=>3}]

答案 1 :(得分:0)

添加到@StasS答案,更直接的哈希方式(使用更加神秘的代码)是这样的:

> Hash[a.group_by{|g| g['group_id']}.map{|g,s| [g, s.inject(0){|a,b| a + b["candies"]}]}]
 => {1=>7, 2=>3, 3=>7, 4=>3} 

你可以像这样展开这条线:

groups = a.group_by{|g| g['group_id']}
id_candies_pairs = groups.map{|g,s| [g, s.inject(0){|a,b| a + b["candies"]}]}
id_candies_hash = Hash[id_candies_pairs]
return id_candies_hash

答案 2 :(得分:0)

重复@StasS的回答,你也可以构建一个更简单的哈希,如:

totals_by_group_id = {}  
a.group_by {|g| g['group_id']}.map do |g, students|  
  totals_by_group_id[g] = students.map {|st| st['candies']}.inject(&:+)  
end

生成的totals_by_group_id哈希是:

{1=>7, 2=>3, 3=>7, 4=>3}