当前位置: 首页 > 知识库问答 >
问题:

Ruby在2个哈希数组上循环并比较键值

毋承基
2023-03-14

我在尝试遍历两个哈希数组时遇到问题。我的哈希值如下所示:

h1= [
  {"name"=>"postgresql", "version"=>29},
  {"name"=>"java", "version"=>8},
  {"name"=>"python", "version"=>3}
]

h2= [
  {"name"=>"postgresql", "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"},
  {"name"=>"java", "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}
]

combined = []

在我检查h1和h2中“name”字段的哈希值后,我需要将这两个哈希组合在一个名为组合的数组中,以便:

  • 如果h1[“name”]==h2[“name“]---

组合数组应如下所示:

combined = [
  {"name"=>"postgresql", "version"=>29, "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"},
  {"name"=>"java", "version"=>8, "release"=>"java-release", "url"=>"https://github.com/repo/java-release"},
  {"name"=> "python", "version"=>3, "release"=> nil, "url"=> nil}
]

我已经尝试了很多,并且总是有更多的迭代和/或在不同名称的情况下无法打印任何内容。

我的代码看起来像:

h1= [{"name"=>"postgresql", "version"=>29}, {"name"=>"java", "version"=>8}, {"name"=>"python", "version"=>3}]

h2= [{"name"=>"postgresql", "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}]

combined = []

h1.each do |h1Key, h1Value|
  h2.each do |h2Key, h2Value|
    if h1["name"] == h2["name"]
      combined << {"name"=> h1["name"], "version"=> h1["version"], "release"=> h2["release"], "url"=> h2["url"]} 
    else
      combined << {"name"=> h1["name"], "version"=> h1["version"], "release"=> nil, "url"=> nil}
    end
  end
end
puts combined.to_s

我也无法正确比较h1和h2的值。

非常感谢您的帮助,因为我对Ruby还很陌生,不幸的是,我的逻辑无法帮助我。

提前感谢!^^

共有3个答案

太叔永新
2023-03-14

可能有很多方法可以做到这一点,但由于你的内部哈希本质上有一个键,所以首先想到的是将你的哈希数组转换为哈希数组,然后简单地使用Hash#deep_merge,这正是这种方法。

hash1 = h1.index_by { |inner_hash| inner_hash['name'] }
hash2 = h2.index_by { |inner_hash| inner_hash['name'] }
combined_hash = hash1.deep_merge(hash2)
combined = combined_hash.values

这给出了除python nil URL之外的预期输出。如果无法在数据中修复该问题,要复制该结果,请尝试如下操作:

# ... as before
defaults = {'url' => nil, 'version' => nil}
combined_hash = combined_hash.transform_values { |v| defaults.merge(v) }
combined = combined_hash.values

如果您需要默认值是数据中可能更改的确切键:

keys = (hash1.keys + hash2.keys).uniq
defaults = keys.map { |k| [k, nil] }.to_h
诸腾
2023-03-14

您可以尝试此代码:

combined = h1
  .concat(h2)
  .group_by { |a| a['name'] }
  .values
  .map do |a|
    res = a.first.merge(a.last)
    res['release'] ||= nil
    res['url'] ||= nil
    res
  end

如果您不确定代码是什么,请尝试逐步执行。

鄢英哲
2023-03-14

首先,h1和h2是散列的数组,而不是散列本身。如果对它们进行迭代,得到的是数组中的每个散列,而不是某个散列的键和值。

为清楚起见,让我们将它们重命名为 a1a2

a1= [{"name"=>"postgresql", "version"=>29}, {"name"=>"java", "version"=>8}, {"name"=>"python", "version"=>3}]
a2= [{"name"=>"postgresql", "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}]

combined = []

现在,当我们迭代它们时,我们依次获得每个哈希。

a1.each do |h1|

对于第一个数组中的每个哈希,我们希望在第二个数组中找到相应的哈希。如果我们在第一个数组中查看java并在第二个数组中找到postgresql,这并不意味着没有java。我们只需要暂时忽略它。如果我们没有找到匹配项,那么我们将分配 nil-s

h2 = a2.find { |h| h1["name"] == h["name"] } || {}

现在我们已经找到了匹配项或没有找到匹配项,我们可以像您所做的那样将结果添加到组合数组中。

combined << {"name"=> h1["name"], "version"=> h1["version"], "release"=> h2["release"], "url"=> h2["url"]}

所有这些:

a1= [{"name"=>"postgresql", "version"=>29}, {"name"=>"java", "version"=>8}, {"name"=>"python", "version"=>3}]
a2= [{"name"=>"postgresql", "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}]

combined = []

a1.each do |h1|
  h2 = a2.find { |h| h1["name"] == h["name"] } || {}
  combined << {"name"=> h1["name"], "version"=> h1["version"], "release"=> h2["release"], "url"=> h2["url"]} 
end
puts combined.to_s #=> [{"name"=>"postgresql", "version"=>29, "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "version"=>8, "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}, {"name"=>"python", "version"=>3, "release"=>nil, "url"=>nil}]

稍微简单一点的方法是使用map。然后可以避免附加数组和手动追加

a1= [{"name"=>"postgresql", "version"=>29}, {"name"=>"java", "version"=>8}, {"name"=>"python", "version"=>3}]
a2= [{"name"=>"postgresql", "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}]

combined = a1.map do |h1|
  h2 = a2.find { |h| h1["name"] == h["name"] } || {}
  {"name"=> h1["name"], "version"=> h1["version"], "release"=> h2["release"], "url"=> h2["url"]} 
end
puts combined.to_s #=> [{"name"=>"postgresql", "version"=>29, "release"=>"postgresql-release", "url"=>"https://github.com/repo/postgresql-release"}, {"name"=>"java", "version"=>8, "release"=>"java-release", "url"=>"https://github.com/repo/java-release"}, {"name"=>"python", "version"=>3, "release"=>nil, "url"=>nil}]

另一个可能的改进是使用merge。

combined = a1.map do |h1|
  h2 = a2.find { |h| h1["name"] == h["name"] } || { "release" => nil, "url" => nil}
  h1.merge(h2)
end
 类似资料:
  • 我正在尝试使用Sinatra和BCrypt实现一种看似非常简单的身份验证方法,但显然我遗漏了一些东西... 用户会预先分配一个临时密码,该密码以明文形式存储在DB中。 我根据临时口令进行身份验证,然后创建salt和password_hash,并将它们作为字符串写入db(本例中为mongo)。 为了进行身份验证,我从db和用户口令中获取salt进行比较。 bcrypt::Engine.hash_se

  • 我有两个哈希数组: 我想在< code>a2中找到其< code>ID和< code>name字段与< code>a1中条目的< code>ID和< code>name字段相匹配的散列(不考虑< code>email或任何其他进入< code>a2的项目),然后将< code>ORDER_NO的值合并到< code>a1散列中也就是说,以下列方式结束: 我也想忽略 a2 中存在的元素,但不忽略 a

  • 我是powershell的新手。我想知道为什么下面的代码总是返回“false”: 什么时候 一个文件是另一个文件的副本 "get-filehash tn|selet-ject hash"为两个文件返回相同的值 两个文件都在同一个目录中 Tnx提前为您解答!

  • 我使用mitsuhiko的pbkdf2实现进行密码哈希: 此函数返回二进制摘要,然后将其编码在bas64中并保存到数据库中。此外,当用户登录时,Base64字符串被设置为cookie。 此函数用于密码哈希比较: 我想知道在安全性方面,二进制哈希和Base64字符串的比较是否有任何不同?例如,当用户登录时,我会计算提交密码的二进制摘要,从数据库中解码Base64字符串,然后比较两个二进制哈希,但是如

  • 嗨,我有两个哈希数组,如下所示 如何将它们合并到单个哈希数组中作为〔{“name”= 因为我需要根据哈希转换的管道分隔cucumber表来验证它们,例如|name|value|rihan|true||gihan|true| 对于cucumber表,我使用以下函数将其转换为哈希 对于实际的 JSON 响应,我正在使用递归函数将其提取到两个哈希数组 [A] 和 [B] 上方,但我不确定如何合并它们以与

  • 有人能告诉我如何从WooCommerce网络钩子中重新创建哈希以与请求中的“X-WC-Webhook-Signature”标头哈希进行比较吗? 留档指定哈希是从“有效负载”生成的,但我无法生成相同的哈希。 我的API是。NET Core 3.1 我尝试的第一件事: 第二个: