【问题标题】:Ruby compare hash values by the same keysRuby 通过相同的键比较哈希值
【发布时间】:2021-11-15 16:04:10
【问题描述】:

假设我有 3 个哈希

hash1 = {'a' => 1, 'b' => 2}
hash2 = {'a' => 1, 'b' => 2, 'd' => 3}
hash3 = {'a' => 1, 'b' => 2, 'c' => 4, 'd' => 3}
hash4 = {'c' => 4, 'd' => 3, 'e' = 5}

预期结果

hash1 == hash2 # => true
hash1 == hash3 # => true
hash1 == hash4 # => false (has no common keys to compare their values)
hash2 == hash3 # => true

所以基本上我想在比较时比较两个哈希中相同键的值。如果没有公共键,则返回 false

编辑: @CarySwoveland 的提示,他的解决方案非常有效:

common_keys = hash1.keys & hash2.keys;

    if common_keys.any?
      hash1.values_at(*common_keys) == hash2.values_at(*common_keys);
    else
      false
    end

【问题讨论】:

  • 你需要一个方法,例如test(hash1, hash2)或覆盖==?
  • @razvans 最好有一个方法,而不是猴子补丁
  • 试试这个:common_keys = hash1.keys & hash2.keys; hash1.values_at(*common_keys) == hash2.values_at(*common_keys).
  • @CarySwoveland 这取决于任何特定的顺序?
  • @Danyil - 未成年人,但你可以写common_keys.any? && hash1.values_at(*common_keys) == [...]

标签: ruby-on-rails ruby hash


【解决方案1】:

如果我得到正确的答案,您可以使用Set,并检查第一个哈希是否包含在第二个中:

require 'set'

def is_included?(hash_a, hash_b)
  return hash_a.size == (hash_a.to_set & hash_b.to_set).size
end

所以,你可以这样检查:

hash1 = {'a' => 1, 'b' => 2}
hash2 = {'a' => 1, 'b' => 2, 'd' => 3}
hash3 = {'a' => 1, 'b' => 2, 'c' => 4, 'd' => 3}
hash4 = {'c' => 4, 'd' => 3, 'e' => 5}

is_included?(hash1, hash2) #=> true
is_included?(hash1, hash3) #=> true
is_included?(hash1, hash4) #=> false
is_included?(hash2, hash3) #=> true

也只是 return hash_a.to_set <= hash_b.to_set 应该可以工作。

【讨论】:

  • 如果 first = { a:1, b:2 } 和 second = { c:3, a:1 }` 您的方法返回 false,但 first[:a] == second[:a] #=> true, :a 是两个哈希的唯一共同键.
  • 你是对的。我刚刚检查了预期的结果。即使我更改为return (hash_a.to_set & hash_b.to_set).any? 以匹配您的示例,我对hash3 与hash4 的预期结果仍有疑问。
【解决方案2】:

编辑:此解决方案不适用于原始问题中未提及的某些情况,因此此答案应该更适合:https://stackoverflow.com/a/69280216/299774

这个公式会给你你想要的(对于提供的例子)

def compare(first, second)
  ((first.to_a & second.to_a) <=> first.to_a) >= 0
end

它是如何工作的?

它将散列转换为键值对数组(也是数组)

> hash1.to_a
=> [["a", 1], ["b", 2]]

所以现在你可以做一些简洁的事情,将数组视为集合并找到它们的交集(公共元素):

> hash1.to_a & hash2.to_a
=> [["a", 1], ["b", 2]]
> hash1.to_a & hash4.to_a
=> []

剩下的是检查交集是否包含在其中一个数组中,火箭方法&lt;=&gt;非常有用,当数组相同时会给你0,如果右边的数组包含在左边,则为1 1,否则为 -1。您似乎对前两种情况感兴趣,因此&gt;= 0

【讨论】:

  • 如果 first = { a:1, b:2 } 和 second = { c:3, a:1 } 您的方法返回 false,但 first[:a] == second[:a] #=&gt; true、:a 是两个哈希的唯一共同键。
  • 是的,@iGian 的回答比stackoverflow.com/a/69280216/299774 好得多,应该被接受(在这个上面添加一个注释)。
猜你喜欢
  • 2016-11-21
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
相关资源
最近更新 更多