ruby-on-rails - 如何在 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"}]
以上是我在哈希数组中的输入
- 按日期在 array_of_hash1 中添加价格和税金
- 按日期在 array_of_hash2 中添加价格和税金
- 减去 (i) - (ii)
- 如果按日期在 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"}]
解决方案
对 DRY 代码使用两个辅助方法并使用Enumerable#sum、Enumerable#group_by、Hash#merge、Hash#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#tap和Hash#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}]
推荐阅读
- callback - 来自按钮 n_clicks 的回调卡片颜色
- c# - Entity Framework Core,如何为 .HasOptional 配置可空外键等效项
- c# - C#soap 调用正在生成 HEAD 请求并且外部服务器正在阻塞。如何去除这些?
- node.js - 如何在不需要刷新页面的情况下与区块链交互
- azure - Azure.Data.Table 无法初始化 TableClient 或 TableServerClient
- regex - 正则表达式在 O365 传输规则中不起作用
- php - 如何防止 foreach 循环不删除重复项
- mdx - EazyBI - 为什么它不计算我的自定义计算度量?
- npm - 如何在不将其添加到 package.json 文件的情况下使用 VIM 插件?
- r - 随机森林输出的敏感性/特异性