Я хотел бы заменить каждое value
в хеше на value.some_method
.
Например, для заданного простого хеша:
{"a" => "b", "c" => "d"}`
каждое значение должно быть .upcase
d, поэтому оно выглядит так:
{"a" => "B", "c" => "D"}
Я пробовал #collect
и #map
всегда просто возвращал массивы. Есть ли элегантный способ сделать это?
ОБНОВИТЬ
Блин, я забыл: хеш находится в переменной экземпляра, которую нельзя менять. Мне нужен новый хеш с измененными значениями, но я бы предпочел не определять эту переменную явно, а затем перебирать хеш, заполняя ее. Что-то вроде:
new_hash = hash.magic{ ... }
Ответы:
или, если вы предпочитаете сделать это неразрушающим образом, и вернуть новый хеш вместо изменения
my_hash
:Эта последняя версия имеет дополнительное преимущество, заключающееся в том, что вы также можете преобразовывать ключи.
источник
each_with_object
- более удобный вариант,inject
когда вы не хотите заканчивать блок хешем:my_hash.each_with_object({}) {|(k, v), h| h[k] = v.upcase }
a_new_hash = Hash[ my_hash.map { |k, v| [k, v.upcase] } ]
.to_h
Поскольку
ruby 2.4.0
вы можете использовать собственныйHash#transform_values
метод:Есть и деструктивная
Hash#transform_values!
версия.источник
Вы можете собрать значения и снова преобразовать их из массива в хэш.
Как это:
источник
Это сделает это:
В отличие
inject
от преимущества, вам не нужно снова возвращать хеш внутри блока.источник
Попробуйте эту функцию:
источник
В ActiveSupport v4.2.0 есть способ для этого . Он вызывается
transform_values
и в основном просто выполняет блок для каждой пары ключ-значение.Поскольку они делают это с помощью,
each
я думаю, что нет лучшего способа, чем пройти через цикл.Обновить:
Начиная с Ruby 2.4.0, вы можете использовать
#transform_values
и#transform_values!
.источник
Вы можете пойти еще дальше и сделать это с вложенным хешем. Конечно, это случается довольно часто с проектами Rails.
Вот код, чтобы гарантировать, что хеш params находится в UTF-8:
источник
Я делаю примерно так:
Это дает вам возможность преобразовать ключ или значение с помощью любого выражения (и это, конечно, неразрушающее).
источник
В Ruby есть
tap
метод ( 1.8.7 , 1.9.3 и 2.1.0 ), который очень полезен для подобных вещей.источник
Рельсы конкретных
Если кому-то нужно только вызвать
to_s
метод для каждого из значений и не использовать Rails 4.2 (который включает ссылку наtransform_values
метод ), вы можете сделать следующее:Примечание: использование библиотеки json обязательно.
Примечание 2: это также превратит ключи в струны
источник
Если вы знаете, что значения являются строками, вы можете вызвать для них метод replace во время цикла: таким образом вы измените значение.
Altohugh это ограничено случаем, когда значения являются строками и, следовательно, не отвечает на вопрос полностью, я подумал, что это может быть полезно для кого-то.
источник
источник