values rails method into create array ruby syntax hash

ruby - rails - ¿Cómo cambiar los valores de Hash?



hash.map ruby (12)

Me gustaría reemplazar cada value en un hash con value.some_method .

Por ejemplo, dado un hash simple:

{"a" => "b", "c" => "d"}`

cada valor debe ser .upcase d, por lo que se ve así:

{"a" => "B", "c" => "D"}

Intenté #collect y #map pero siempre #map las matrices. ¿Hay una manera elegante de hacer esto?

ACTUALIZAR

Maldita sea, lo olvidé: el hash está en una variable de instancia que no debería cambiarse. Necesito un hash nuevo con los valores modificados, pero preferiría no definir esa variable explícitamente y luego pasar por encima del hash que la llena. Algo como:

new_hash = hash.magic{ ... }



Es posible que desee ir un paso más allá y hacer esto en un hash anidado. Ciertamente, esto ocurre bastante con los proyectos de Rails.

Aquí hay un código para asegurarse de que hash de params esté en UTF-8:

def convert_hash hash hash.inject({}) do |h,(k,v)| if v.kind_of? String h[k] = to_utf8(v) else h[k] = convert_hash(v) end h end end # Iconv UTF-8 helper # Converts strings into valid UTF-8 # # @param [String] untrusted_string the string to convert to UTF-8 # @return [String] your string in UTF-8 def to_utf8 untrusted_string="" ic = Iconv.new(''UTF-8//IGNORE'', ''UTF-8'') ic.iconv(untrusted_string + '' '')[0..-2] end


Esto lo hará:

my_hash.each_with_object({}) { |(key, value), hash| hash[key] = value.upcase }

A diferencia de inject la ventaja es que no necesita devolver el hash nuevamente dentro del bloque.


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-par.

Como lo están haciendo con each , creo que no hay mejor manera de pasar.

hash = {sample: ''gach''} result = {} hash.each do |key, value| result[key] = do_stuff(value) end


Prueba esta función:

h = {"a" => "b", "c" => "d"} h.each{|i,j| j.upcase!} # now contains {"a" => "B", "c" => "D"}.


Puede recopilar los valores y convertirlos de Array a Hash nuevamente.

Me gusta esto:

config = Hash[ config.collect {|k,v| [k, v.upcase] } ]


Ruby tiene el método tap ( 1.8.7 , 1.9.3 y 2.1.0 ) que es muy útil para cosas como esta.

original_hash = { :a => ''a'', :b => ''b'' } original_hash.clone.tap{ |h| h.each{ |k,v| h[k] = v.upcase } } # => {:a=>"A", :b=>"B"} original_hash # => {:a=>"a", :b=>"b"}


Si sabe que los valores son cadenas, puede llamar al método de replace mientras está dentro del ciclo: de esta manera, cambiará el valor.

Altohugh esto se limita al caso en que los valores son cadenas y por lo tanto no responde la pregunta completamente, pensé que puede ser útil para alguien.


Yo hago algo como esto:

new_hash = Hash [* original_hash.collect {| key, value | [clave, valor + 1]}. aplanar]

Esto le proporciona las facilidades para transformar la clave o valor a través de cualquier expresión también (y no es destructivo, por supuesto).


Rails-specific

En caso de que alguien solo necesite llamar to_s método to_s para cada uno de los valores y no utilice Rails 4.2 (que incluye el link método transform_values ), puede hacer lo siguiente:

original_hash = { :a => ''a'', :b => BigDecimal(''23.4'') } #=> {:a=>"a", :b=>#<BigDecimal:5c03a00,''0.234E2'',18(18)>} JSON(original_hash.to_json) #=> {"a"=>"a", "b"=>"23.4"}

Nota: Se requiere el uso de la biblioteca ''json''.

Nota 2: Esto convertirá las claves en cadenas también


my_hash.each { |k, v| my_hash[k] = v.upcase }

o, si prefieres hacerlo de forma no destructiva, y devuelves un nuevo hash en lugar de modificar my_hash :

a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k] = v.upcase; h }

Esta última versión tiene el beneficio adicional de que también puede transformar las claves.


new_hash = old_hash.merge(old_hash) do |_key, value, _value| value.upcase end # old_hash = {"a" => "b", "c" => "d"} # new_hash = {"a" => "B", "c" => "D"}