arrays - 根据多个键的比较合并两个哈希数组

标签 arrays ruby hash

我有两个哈希数组:

a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" }, ...]
a2 = [{ ID: 12496, name: "Robert", ORDER_NO: 5511426 }, ...]

我想在 a2 中找到哈希值谁的IDname字段匹配 IDname a1 中条目的字段(不关心 email 或进入 a2 的任何其他项目),然后合并 ORDER_NO 的值进入a1散列这些值。即结束于:

[{ ID: 12496, name: "Robert", email: "robert@example.com", ORDER_NO: 5511426 } ...]

此外,我想忽略 a2 中存在但 a1 中不存在的元素。

我正在做以下事情:

a1.each do |a1_hash|
  matching_hash = a2.find { |a2_hash| data_matches?(a1_hash, a2_hash) } if a2.present?
  a1_hash["ORDER_NO"] = a2_hash["ORDER_NO"] if matching_hash.present?
  a2.delete(a2_hash)
end

但是有没有更快的方法呢?

最佳答案

这可以使用一些 Ruby 的内置方法非常干净地完成。

a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" },
      { ID: 12497, name: "Lola",   email: "lola@hotmail.com" },
      { ID: 12498, name: "Hank",   email: "hank@hotmail.com" }]

a2 = [{ ID: 12497, name: "Lola",   ORDER_NO: 5511427 },
      { ID: 12496, name: "Robert", ORDER_NO: 5511426 }]

index = a2.group_by{|entry| [entry[:ID], entry[:name]] }
a1.map{|entry| (index[[entry[:ID], entry[:name]]] || []).reduce(entry, :merge) }

结果:

[{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com", :ORDER_NO=>5511426},
 {:ID=>12497, :name=>"Lola",   :email=>"lola@hotmail.com",   :ORDER_NO=>5511427},
 {:ID=>12498, :name=>"Hank",   :email=>"hank@hotmail.com"}]

分割:

首先,我们使用group_by构建 a2 中的条目表,这些条目可能会合并到 a1 中的条目中。我们在 id 和 name 键上索引这个表,因为这些是我们用来确定哪些条目匹配的因素:

index = a2.group_by{|entry| [entry[:ID], entry[:name]] }

这会产生结果:

{[12497, "Lola"]=>[{:ID=>12497,   :name=>"Lola",   :ORDER_NO=>5511427}], 
 [12496, "Robert"]=>[{:ID=>12496, :name=>"Robert", :ORDER_NO=>5511426}]}

接下来,我们map a1 中的每个条目到其新形式,合并索引中的订单号:

a1.map{|entry|
  # ...
}

为了获取我们将每个条目映射到的值,我们首先获取一个数组,其中包含 a2 中适合与 a1 中的此条目合并的所有值>:

(index[[entry[:ID], entry[:name]]] || [])

这将为 Lola 返回类似 [{:ID=>12497, :name=>"Lola", :ORDER_NO=>5511427}] 的内容,并为 Hank 返回一个空数组,他有a2 中没有匹配项。

然后,从 a1 的条目开始,我们 reduce使用 merge 从索引到一个散列的所有条目(例如 reduce(entry, :merge)),这会导致像 {:ID=>12496, :name=>"Robert", :email=>"robert@hotmail 这样的条目.com", :ORDER_NO=>5511426}.

如果您不熟悉 Ruby 核心库中的方法,那么所有这些看起来可能有点复杂。但是,一旦您理解了 map 和 reduce 等简单的函数式编程概念,想出像这样简单而强大的解决方案就真的不难了。

关于arrays - 根据多个键的比较合并两个哈希数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30567740/

相关文章:

javascript - 如何从拆分数组函数中乘以数据

c - 在 malloc 中使用 sizeof(void)

ruby-on-rails - 动态生成的内容不会环绕 float 图像

ruby - 在 Ruby 中使用包?

c# - 发布站点上的加密类

ruby - 如何在 Ruby 中设置数据结构以进行高效搜索?

java - 从同一个类中的另一个方法调用一个方法

ruby-on-rails - 使用 STI 时,如何强制 Rails 在 link_to 帮助程序中使用父类(super class)名称?

mysql - 为 mysql 编译了 sha256 库,但它产生的散列不同于 dovecot 的 sha256

php - 从 array_rand 函数的结果创建简码