Подтвердить что ты не робот

Ruby: Какой самый простой способ обновить значения Hash?

Скажи:

h = { 1 => 10, 2 => 20, 5 => 70, 8 => 90, 4 => 34 }

Я хотел бы изменить каждое значение v на foo(v), так что h будет:

h = { 1 => foo(10), 2 => foo(20), 5 => foo(70), 8 => foo(90), 4 => foo(34) }

Какой самый элегантный способ достичь этого?

4b9b3361

Ответ 1

Вы можете использовать update (псевдоним merge!) для обновления каждого значения с помощью блока:

hash.update(hash) { |key, value| value * 2 }

Обратите внимание, что мы эффективно объединяем hash с собой. Это необходимо, потому что Ruby вызовет блок для разрешения слияния для любых ключей, которые сталкиваются, установив значение с возвращаемым значением блока.

Ответ 2

Rails (и Ruby 2. 4+ изначально) имеют Hash#transform_values, так что теперь вы можете сделать {a:1, b:2, c:3}.transform_values{|v| foo(v)}

https://ruby-doc.org/core-2.4.0/Hash.html#method-i-transform_values

Если вам нужно, чтобы он работал и во вложенных хэшах, у Rails теперь есть deep_transform_values(источник):

hash = { person: { name: 'Rob', age: '28' } }

hash.deep_transform_values{ |value| value.to_s.upcase }
# => {person: {name: "ROB", age: "28"}}

Ответ 3

Это сделает:

h.each {|k, v| h[k] = foo(v)}

Ответ 4

Следующее немного быстрее, чем @Dan Cheail для больших хэшей, и немного более функционально-программируемого стиля:

new_hash = Hash[old_hash.map {|key, value| key, foo(value)}]

Hash#map создает массив пар значений ключа, а Hash.[] преобразует массив пар в хэш.

Ответ 5

Есть несколько способов сделать это; самым прямым способом было бы использовать Hash#each для обновления нового хэша:

new_hash = {}
old_hash.each do |key, value|
  new_hash[key] = foo(value)
end