我有一个Ruby哈希,它的键值可能相同-例如,相同的数组。
我将如何编写一种方法(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]
group_by
由于Ruby并不真正在乎将数组与数组进行比较,将字符串与字符串进行比较,还是将符号与符号进行比较,因此可以直接使用# 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)
进行简单处理。这同样适用于其他类型的数据。
这里的关键是去除非重复项,然后从分组的数组中提取结果的关键。如果您想知道匹配的组,可以将
group_by
(将它们全部组合成一个数组)切换到flat_map
,以使它们分开。如果您有两组不同的重复值,则将返回类似map
的结果。
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] ||= []) << k
附加到空数组。如果k
具有键h
,则表达式简化为k
。