首页 > 解决方案 > 如何在 ruby​​ on rails 中添加和合并来自不同哈希数组的值

问题描述

array_of_hash1 = 
    [{"Date" => "2019-07-01", "Country" => "US", "Email" => "sample1@gmail.com", "Price" => "11.224323", "Tax" => "8.55443"},
     {"Date" => "2019-07-01", "Country" => "US", "Email" => "sample2@gmail.com", "Price" => "16.664323", "Tax" => "6.55443"},
     {"Date" => "2019-06-30", "Country" => "US", "Email" => "sample3@gmail.com", "Price" => "17.854323", "Tax" => "7.12343"},
     {"Date" => "2019-07-02", "Country" => "UK", "Email" => "sample4@gmail.com", "Price" => "14.224323", "Tax" => "4.32443"}]

array_of_hash2 = 
    [{"Date" => "2019-07-01", "Name" => "John", "Price" => "11.3442223", "Tax" => "3.44343"},
     {"Date" => "2019-07-01", "Name" => "Jack", "Price" => "14.332323", "Tax" => "5.41143"},
    {"Date" => "2019-07-02", "Name" => "Sam", "Price" => "10.2223443", "Tax" => "2.344552"}]

以上是我在哈希数组中的输入

  1. 按日期在 array_of_hash1 中添加价格和税金
  2. 按日期在 array_of_hash2 中添加价格和税金
  3. 减去 (i) - (ii)
  4. 如果按日期在 array_of_hash2 中没有值,则与 array_of_hash1 进行比较。然后仅从 array_of_hash1 中获取值。

这是我的预期输出。

预期输出:

[{"Date" => "2019-07-01", "Country" => "US", "Email" => "sample1@gmail.com", "Price" => "2.2121007000000006", "Tax" => "6.254"}, 
 {"Date" => "2019-07-02", "Country" => "UK", "Email" => "sample4@gmail.com", "Price" => "4.0019787", "Tax" => "1.9798780000000002"},
{"Date" => "2019-06-30", "Country" => "US", "Email" => "sample3@gmail.com", "Price" => "17.854323", "Tax" => "7.12343"}]

标签: ruby-on-railsruby

解决方案


对 DRY 代码使用两个辅助方法并使用Enumerable#sumEnumerable#group_byHash#mergeHash#transform_values以及您可以在文档中找到的其他方法。

我在这里也使用Object#then

def sum_price_tax(ary)
  ary.first.merge ary.then { |ary| { "Price" => ary.sum { |h| h["Price"].to_f }, "Tax" => ary.sum { |h| h["Tax"].to_f} }  }
end

def group_and_sum(array_of_hash)
  array_of_hash.group_by { |h| h["Date"] }.transform_values { |ary| sum_price_tax(ary) }
end

定义方法后,您可以执行以下操作:

a1 = group_and_sum(array_of_hash1)
a2 = group_and_sum(array_of_hash2)
a1.map { |k, v| v.merge(a2[k] || {}) { |h, old_val, new_val| old_val.is_a?(Float) ? old_val - new_val : old_val  } }

#=> [{"Date"=>"2019-07-01", "Country"=>"US", "Email"=>"sample1@gmail.com", "Price"=>2.2121007000000006, "Tax"=>6.254, "Name"=>"John"}, {"Date"=>"2019-06-30", "Country"=>"US", "Email"=>"sample3@gmail.com", "Price"=>17.854323, "Tax"=>7.12343}, {"Date"=>"2019-07-02", "Country"=>"UK", "Email"=>"sample4@gmail.com", "Price"=>4.0019787, "Tax"=>1.9798780000000002, "Name"=>"Sam"}]

以这种方式也"Name"存在。


您可以摆脱的一种方法"Name"是使用Object#tapHash#delete

a1.map { |k, v| v.merge(a2[k] || {}) { |h, old_val, new_val| old_val.is_a?(Float) ? old_val - new_val : old_val  }.tap { |h| h.delete("Name") } }

#=> [{"Date"=>"2019-07-01", "Country"=>"US", "Email"=>"sample1@gmail.com", "Price"=>2.2121007000000006, "Tax"=>6.254}, {"Date"=>"2019-06-30", "Country"=>"US", "Email"=>"sample3@gmail.com", "Price"=>17.854323, "Tax"=>7.12343}, {"Date"=>"2019-07-02", "Country"=>"UK", "Email"=>"sample4@gmail.com", "Price"=>4.0019787, "Tax"=>1.9798780000000002}]

推荐阅读