首页 > 解决方案 > 根据特定 ID 合并和求和哈希值,并保持剩余的哈希不变

问题描述

我尝试了多种方法,包括group_by并且sum因为我的数组中有两个不同的结构化哈希,所以我很难解决它。

这是我的数据结构:

{
DRIVER NAME: [
{
pb_id: "133599.0",
pbbname: "Company 1,
opl_amount: "101.0",
ops_type: "P",
ops_stop_id: 269802,
ops_order_id: 133599,
ops_driver1: 11,
ops_delivered_time: null
},
{
pb_id: "133599.0",
pbbname: "Company 1",
opl_amount: "11.62",
ops_type: "P",
ops_stop_id: 269802,
ops_order_id: 133599,
ops_driver1: 11,
ops_delivered_time: null
},
{
pb_id: "133699.0",
pbbname: "Company 1",
opl_amount: "66.0",
ops_type: "P",
ops_stop_id: 270022,
ops_order_id: 133699,
ops_driver1: 11,
ops_delivered_time: null
},
{
pb_id: "133501.0",
pbbname: "Company 2",
pb_net_rev: "675.0",
ops_driver1: 11,
ops_stop_id: 269587,
dh_first_name: "FIRST NAME",
dh_last_name: "SECOND",
ops_delivered_time: "2021-04-05T13:36:00.000-05:00"
},
]
}

我只想要merge那些objects具有相同pb_id且具有opl_amount key. 如果他们没有opl_amount key,那么他们需要保持原样。这不应该那么难,但同样,我很难执行它。

标签: ruby-on-railsrubyhash

解决方案


我的理解是,如果一组两个或多个哈希值相同,:pb_id那么:

  • 它们都有相同的键,包括一个键:opl_amount
  • 以外的所有键的值:opl_amount都相等;和
  • 它们将被替换为具有相同键和值的单个散列,除了 的值,该值:opt_amount将计算为:opl_amount组中每个散列的值的总和(这需要在字符串和浮点数之间进行转换)。

一种方法是使用Hash#update (aka merge!) 的形式,该形式使用一个块来确定在合并的两个哈希中都存在的键的值。那些被合并的散列将有一个键,即:pb_id.

假设给定的哈希数组如下。

arr = [
  { pb_id: "133599.0", pbbname: "Company 1", opl_amount: "101.0" },
  { pb_id: "133599.0", pbbname: "Company 1", opl_amount: "11.62" },
  { pb_id: "133699.0", pbbname: "Company 1", opl_amount: "66.0" },
  { pb_id: "133501.0", pbbname: "Company 2" }
]

然后我们可以执行以下计算。

arr.each_with_object({}) do |g,h|
  h.update(g[:pb_id]=>g) do |_k,o,n|
    o.merge(opl_amount: (o[:opl_amount].to_f + n[:opl_amount].to_f).to_s)
  end
end.values
  #=> [
  #    {:pb_id=>"133599.0", :pbbname=>"Company 1", :opl_amount=>"112.62"},
  #    {:pb_id=>"133699.0", :pbbname=>"Company 1", :opl_amount=>"66.0"},
  #    {:pb_id=>"133501.0", :pbbname=>"Company 2"}
  #   ]

发现的接收者Hash#values是:

{"133599.0"=>{:pb_id=>"133599.0", :pbbname=>"Company 1", :opl_amount=>"112.62"},
 "133699.0"=>{:pb_id=>"133699.0", :pbbname=>"Company 1", :opl_amount=>"66.0"},
 "133501.0"=>{:pb_id=>"133501.0", :pbbname=>"Company 2"}}

确定要合并的两个哈希中存在的键值的块是:

do |_k,o,n|
  o.merge(opl_amount: (o[:opl_amount].to_f + n[:opl_amount].to_f).to_s)
end

正如文档中解释的那样update

  • _k是通用键1
  • o是“旧”散列,这里是正在构造的散列,由块变量保存h
  • n是“新”哈希,在这里{ g[:pb_id]=>g }(可选地表示g[:pb_id]=>g为方法的参数)

请注意,在以下情况下不会调用解析块:

  • 具有唯一值的散列:pb_id被合并到h(包括没有键的散列:opt_amount)和
  • 一组具有相同值的散列的第一个散列:pb_id被合并到h.

1. 当块计算中不使用块变量时,通常的做法是通过使用前导下划线命名变量来向读者表明这一事实,通常仅使用下划线 ( |_,o,n|)。


推荐阅读