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
, выражение уменьшается до h[v] << k
.