Me gustaría reemplazar cada uno value
en un hash con value.some_method
.
Por ejemplo, para un hash simple dado:
{"a" => "b", "c" => "d"}`
cada valor debe ser .upcase
d, por lo que se ve así:
{"a" => "B", "c" => "D"}
Lo intenté #collect
y #map
siempre obtengo los arreglos. ¿Hay alguna forma elegante de hacer esto?
ACTUALIZAR
Maldición, lo olvidé: el hash está en una variable de instancia que no debe cambiarse. Necesito un nuevo hash con los valores modificados, pero preferiría no definir esa variable explícitamente y luego recorrer el hash llenándolo. Algo como:
new_hash = hash.magic{ ... }
Respuestas:
o, si prefiere hacerlo de forma no destructiva, y devolver un nuevo hash en lugar de modificarlo
my_hash
:Esta última versión tiene el beneficio adicional de que también podría transformar las claves.
fuente
each_with_object
es una versión más conveniente deinject
cuando no quieres terminar el bloque con el hash: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
Como
ruby 2.4.0
puedes usar elHash#transform_values
método nativo :También hay una
Hash#transform_values!
versión destructiva .fuente
Puede recopilar los valores y convertirlos de Array a Hash nuevamente.
Me gusta esto:
fuente
Esto lo hará:
En contraposición a
inject
la ventaja es que no es necesario devolver el hash nuevamente dentro del bloque.fuente
Prueba esta función:
fuente
Hay un método para eso en ActiveSupport v4.2.0. Se llama
transform_values
y básicamente solo ejecuta un bloque para cada par clave-valor.Como lo están haciendo con un
each
, creo que no hay mejor manera que recorrerlo.Actualizar:
Desde Ruby 2.4.0 puedes usar
#transform_values
y#transform_values!
.fuente
Es posible que desee ir un paso más allá y hacerlo en un hash anidado. Ciertamente, esto sucede bastante con los proyectos de Rails.
Aquí hay un código para garantizar que un hash de params esté en UTF-8:
fuente
Hago algo como esto:
Esto le proporciona las facilidades para transformar la clave o el valor a través de cualquier expresión también (y no es destructivo, por supuesto).
fuente
Ruby tiene el
tap
método ( 1.8.7 , 1.9.3 y 2.1.0 ) que es muy útil para cosas como esta.fuente
Carriles específicos
En caso de que alguien solo necesite llamar al
to_s
método a cada uno de los valores y no esté usando Rails 4.2 (que incluye el enlace deltransform_values
método ), puede hacer lo siguiente:Nota: Se requiere el uso de la biblioteca 'json'.
Nota 2: Esto también convertirá las teclas en cadenas
fuente
Si sabe que los valores son cadenas, puede llamar al reemplazo método de en ellos durante el ciclo: de esta manera cambiará el valor.
Altohugh, esto se limita al caso en el que los valores son cadenas y, por lo tanto, no responde la pregunta por completo, pensé que podría ser útil para alguien.
fuente
fuente