【问题标题】:Combine Hash and sum the values in ruby组合 Hash 并对 ruby​​ 中的值求和
【发布时间】:2022-11-17 22:31:30
【问题描述】:

我有以下哈希:

{"shape":[  
  {"key":"0000round","total_amount":"54679110.10","name":"Round","count":100},     
  {"key":"0001square","total_amount":"4074837.00","name":"Square","count":200},
  {"key":"0003rectangle","total_amount":"6114261.00","name":"Rectangle","count":150},
  {"key":"0008round","total_amount":"6425948.50","name":"Round","count":620},
  {"key":"0004square","total_amount":"5009297.50","name":"Square","count":440}
]}

我想对总金额求和并计算一些重复值,例如 0000round0008round

在这种情况下,uniq key 将是Name

所以Name=Round对于Square有两个相似的值。

到目前为止我尝试了什么:

temp_hash = Hash.new(nil)
raw_hash['shape'].each do |shape|
  if temp_hash[shape['name']].present?
    temp_hash[shape['name']]['total_amount'] = temp_hash[shape['name']]['total_amount'].to_f + shape['total_amount'].to_f
    temp_hash[shape['name']]['count'] = temp_hash[shape['name']]['count'].to_i + shape['count'].to_i
    temp_hash[shape['name']]['key'] = [temp_hash[shape['name']]['key'] , shape['key']].flatten    
  else
    temp_hash[shape['name']] = shape
  end

raw_hash['shape'] = temp_hash.values 
end

输出是

{"shape"=>[
{"key"=>["0000round", "0004round"],"total_amount"=>59688407.6,"name"=>"Round","count"=>7437},
{"key"=>"0001princess","total_amount"=>"4074837.00","name"=>"Princess","count"=>810},
{"key"=>["0003oval", "0008oval"],"total_amount"=>12540209.5,"name"=>"Oval","count"=>1460}]}

有更好的方法吗?

【问题讨论】:

    标签: ruby hash


    【解决方案1】:

    首先,我们将定义一个Hash,它告诉我们每个键值应该如何合并:

    merger = {
      key: -> *values { values },
      total_amount: -> *values { values.sum(&:to_f) },
      count: -> *values { values.sum },
      name: -> *values { values.last }
    }
    

    很快就会明白我们用它做什么。

    我们需要通过 :name 键对 Hash 进行分组:

    grouped_hash = raw_hash[:shape].group_by {|h| h[:name] }
    

    我们只需要生成的 Hash 的值,而不是键:

    grouped_hashes = grouped_hash.values
    

    我们需要以某种方式转换这个 Array 的值:

    transformed_hashes = grouped_hashes.map {|hashes| … something … }
    

    那么,什么是something?那么,我们需要合并每个组中的所有Hashes,我们需要根据密钥使用不同的功能来执行此操作。这就是为什么我们将 Hash 设为上面的 Procs 的原因。所以,something 看起来像这样:

    hashes.reduce {|acc, hash| acc.merge(hash) {|key, *values| merger[key].(*values) }}
    

    所以,总的结果是这样的:

    merger = {
      key: -> *values { values },
      total_amount: -> *values { values.sum(&:to_f) },
      count: -> *values { values.sum },
      name: -> *values { values.last }
    }
    
    raw_hash[:shape].group_by {|h| h[:name] }.
      values.
      map do |hashes|
        hashes.reduce do |acc, hash|
          acc.merge(hash) do |key, *values|
            merger[key].(*values)
          end
        end
      end
    

    【讨论】:

      猜你喜欢
      • 2018-07-08
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多