具有哈希的Sum数组

时间:2013-11-20 11:04:15

标签: ruby-on-rails ruby ruby-on-rails-3.2

如何在这两个哈希数组之间执行添加,例如我想从第一个数组获取,第一个哈希和sum number, s_number, l_number与第二个数组中的第一个哈希,总和将取决于created_at,如果第一个数组中的created_at与第二个数组中的created_at相等,则执行+。请看看我希望退回的内容,因为我不知道如何更好地解释这一点。

谢谢

raw_data = [
        [
            {"created_at"=>"2013-11-17","number"=>0,"s_number"=>0,"l_number"=>0},
            {"created_at"=>"2013-11-18","number"=>6,"s_number"=>1,"l_number"=>4},
            {"created_at"=>"2013-11-19","number"=>1,"s_number"=>1,"l_number"=>1},
            {"created_at"=>"2013-11-20","number"=>0,"s_number"=>0,"l_number"=>0}
        ],
        [
            {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
            {"created_at"=>"2013-11-18","number"=>1,"s_number"=>41,"l_number"=>1},
            {"created_at"=>"2013-11-19","number"=>5,"s_number"=>45,"l_number"=>7},
            {"created_at"=>"2013-11-20","number"=>7,"s_number"=>8,"l_number"=>2}    
        ]
        ]

应该返回什么

[
        {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
        {"created_at"=>"2013-11-18","number"=>7,"s_number"=>42,"l_number"=>5},
        {"created_at"=>"2013-11-19","number"=>6,"s_number"=>46"l_number"=>8},
        {"created_at"=>"2013-11-20","number"=>7,"s_number"=>8,"l_number"=>2}    
]

更新哈希格式与我发布的内容不同:

{:created_at=>Sun, 17 Nov 2013, :number=>0, :s_number=>0, :l_number=>0}

6 个答案:

答案 0 :(得分:2)

首先,您需要对数组求和:

raw_data.sum

这将返回如下:

    [
        {"created_at"=>"2013-11-17","number"=>0,"s_number"=>0,"l_number"=>0},
        {"created_at"=>"2013-11-18","number"=>6,"s_number"=>1,"l_number"=>4},
        {"created_at"=>"2013-11-19","number"=>1,"s_number"=>1,"l_number"=>1},
        {"created_at"=>"2013-11-20","number"=>0,"s_number"=>0,"l_number"=>0}
        {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
        {"created_at"=>"2013-11-18","number"=>1,"s_number"=>41,"l_number"=>1},
        {"created_at"=>"2013-11-19","number"=>5,"s_number"=>45,"l_number"=>7},
        {"created_at"=>"2013-11-20","number"=>7,"s_number"=>8,"l_number"=>2}    
    ]

现在,我们需要按'created_at'键对元素进行分组:

raw_data.sum.group_by{|element| element['created_at']}

这将导致:

{
    "2013-11-17" => [
        {"created_at"=>"2013-11-17","number"=>0,"s_number"=>0,"l_number"=>0},
        {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
      ],
    "2013-11-18" => [
        {"created_at"=>"2013-11-18","number"=>6,"s_number"=>1,"l_number"=>4},
        {"created_at"=>"2013-11-18","number"=>1,"s_number"=>41,"l_number"=>1}
      ], ...           
}

我们只需要此哈希的值:

raw_data.sum.group_by{|element| element['created_at']}.values

# =>
    [
      [
        {"created_at"=>"2013-11-17","number"=>0,"s_number"=>0,"l_number"=>0},
        {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
      ],
      [
        {"created_at"=>"2013-11-18","number"=>6,"s_number"=>1,"l_number"=>4},
        {"created_at"=>"2013-11-18","number"=>1,"s_number"=>41,"l_number"=>1}
      ], ...           
}

现在我们需要将每个哈希数组映射到一个哈希。为此,我们将使用注入和合并功能与块:

raw_data.sum.group_by{|element| element[:created_at]}.values.map{|a| a.inject({}) {|result, hash| result.merge(hash) {|key, old_value, new_value| key == :created_at ? old_value : old_value + new_value}}}



# =>

[
    {"created_at"=>"2013-11-17","number"=>2,"s_number"=>3,"l_number"=>4},
    {"created_at"=>"2013-11-18","number"=>7,"s_number"=>42,"l_number"=>5},
    {"created_at"=>"2013-11-19","number"=>6,"s_number"=>46"l_number"=>8},
    {"created_at"=>"2013-11-20","number"=>7,"s_number"=>8,"l_number"=>2}    
]

答案 1 :(得分:1)

我会这样做:

result = raw_data.flatten.each_with_object({}) do |hash, result|
  date = hash.delete("created_at")
  result[date] = Hash.new(0) unless result[date]
  hash.each{|key, val| result[date][key] += val}
end.map{|date, hash| hash["created_at"] = date; hash}

p result #=> [{"number"=>2, "s_number"=>3, "l_number"=>4, "created_at"=>"2013-11-17"}, ...

或者甚至更好,因为它会保持哈希的顺序:

result = raw_data.flatten.group_by{|x|x["created_at"]}.values.map do |x| 
  x.inject do |result, hash| 
    result.merge(hash){|key, old, new| old.is_a?(String) ? old : old + new }
  end
end

p result #=> [{"created_at"=>"2013-11-17", "number"=>2, "s_number"=>3, "l_number"=>4},  {"created_at"=>"2013-11-18", "number"=>7, "s_number"=>42, "l_number"=>5} ...

答案 2 :(得分:1)

output = []

raw_data.flatten.group_by {|x| x[:created_at].to_s}.each do |key, values|
  temp_hash = { :created_at => key.to_date }
  [:number, :s_number, :l_number].each do |attr|
    temp_hash[attr] = values.collect{|w| w[attr]}.sum
  end
  output << temp_hash
end

# output will contain your result

答案 3 :(得分:1)

def sum_two_arrays_of_hashes(raw_data, keys = %w[number s_number l_number])
  raw_data[0].map.with_index do |item, index|
    if raw_data[1][index]["created_at"] = item["created_at"]
      sum_hash = {}
      sum_hash["created_at"] = item["created_at"]
      sum_hash.merge keys.inject({}){ |m, k| m[k] = raw_data[1][index][k] + item[k];  m}
    end
  end
end

答案 4 :(得分:1)

我昨天遇到了同样的情况,请查看此链接:

  

How to sum an array with hashes

答案 5 :(得分:1)

尝试下一个代码:

result = raw_data.flatten.group_by{|x|x["created_at"]}.values.map do |x| 
  x.inject do |result, hash| 
    result.merge(hash){|key, old, new| old.is_a?(String) ? old : old + new }
  end
end