【问题标题】:How can I tell which keys, if any, in a ruby hash same the same value?如何判断 ruby​​ 哈希中的哪些键(如果有)具有相同的值?
【发布时间】:2020-06-06 23:45:07
【问题描述】:

我有一个 Ruby 哈希,它可能具有相同值的键——例如,相同的数组。

我将如何编写一个方法 (duplicate_values) 来确定哪些键(如果有)具有相同的值?

duplicate_values 方法应返回具有相同值的键的数组。

例子:

h = {}

h[:a] = [1, 2, 3]

h[:b] = [1, 2, 4]

h.duplicate_values # returns []

h = {}

h[:a] = [1, 2, 3]

h[:b] = [4, 5, 6]

h[:c] = [1, 2, 3]

h.duplicate_values # returns [:a, :c]

【问题讨论】:

  • 这些是相同的对象还是恰好相同的内容

标签: ruby hash


【解决方案1】:

最合乎逻辑的做法是使用group_by

# Group the keys by...
h.keys.group_by do |k|
  # ...the value they contain in the hash.
  h[k]
# Out of those select the entries...
end.select do |k, v|
  # ...that have duplicates.
  v.length > 1
# Then find out what keys those are from the grouped list(s)
end.flat_map(&:last)

由于 Ruby 并不真正关心您是将数组与数组、字符串与字符串还是符号与符号进行比较,因此您可以直接使用 group_by 而不用大惊小怪。这同样适用于其他类型的数据。

这里的关键是去除非重复项,然后从分组数组中提取结果键。

如果您想知道匹配的组,您可以将flat_map(将它们组合成一个数组)切换为map(将它们分开)。如果您有两组不同的重复值,那将返回类似 [[:a,:b],[:f:,g:]] 的结果。

【讨论】:

    【解决方案2】:
    h = { a: [1, 2, 3], b: [4, 5, 6], c:[1, 2, 3], d: [7, 8, 9], e: [4, 5, 6] }
    

    h.each_with_object({}) { |(k,v),h| (h[v] ||= []) << k }.
      select { |_,v| v.size > 1 }.
      flat_map(&:last)
      #=> [:a, :c, :b, :e] 
    

    步骤如下:

    f = h.each_with_object({}) { |(k,v),h| (h[v] ||= []) << k }
      #=> {[1, 2, 3]=>[:a, :c], [4, 5, 6]=>[:b, :e], [7, 8, 9]=>[:d]}
    g = f.select { |_,v| v.size > 1 }
      #=> {[1, 2, 3]=>[:a, :c], [4, 5, 6]=>[:b, :e]}
    g.flat_map(&:last)
      #=> [:a, :c, :b, :e] 
    

    h[v] ||= []
    

    扩展为:

    h[v] = h[v] || []
    

    所以当h 没有键v 时,表达式简化为:

    h[v] = nil || []
      #=> []
    

    v 的值被返回时,(h[v] ||= []) &lt;&lt; kk 追加到空数组中。如果h 有一个键k,则表达式简化为h[v] &lt;&lt; k

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 2014-11-21
      • 2014-09-14
      • 2012-07-31
      • 2011-03-10
      相关资源
      最近更新 更多