Как я могу определить, какие ключи, если таковые имеются, в ruby га sh имеют одинаковое значение? - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть Ruby га sh, у которого могут быть ключи с одинаковым значением - например, с одним и тем же массивом.

Как мне написать метод (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]

Ответы [ 2 ]

3 голосов
/ 23 февраля 2020

Наиболее логичным подходом является использование 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:]], если бы у вас было две разные группы дублированных значений.

0 голосов
/ 23 февраля 2020
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.

...