update rails create array ruby hash

rails - Cambiar cada valor en un hash en Ruby



ruby hash to json (10)

Quiero cambiar cada valor en un hash para agregar ''%'' antes y después del valor para

{ :a=>''a'' , :b=>''b'' }

debe ser cambiado a

{ :a=>''%a%'' , :b=>''%b%'' }

¿Cuál es la mejor manera de hacer esto?


Después de probarlo con RSpec de esta manera:

describe Hash do describe :map_values do it ''should map the values'' do expect({:a => 2, :b => 3}.map_values { |x| x ** 2 }).to eq({:a => 4, :b => 9}) end end end

Puede implementar Hash # map_values ​​de la siguiente manera:

class Hash def map_values Hash[map { |k, v| [k, yield(v)] }] end end

La función entonces se puede usar así:

{:a=>''a'' , :b=>''b''}.map_values { |v| "%#{v}%" } # {:a=>"%a%", :b=>"%b%"}


En Ruby 2.1 y superior puedes hacer

{ a: ''a'', b: ''b'' }.map { |k, str| [k, "%#{str}%"] }.to_h



La mejor manera de modificar los valores de Hash en su lugar es

hash.update(hash){ |_,v| "%#{v}%" }

Menos código e intención clara. También más rápido porque no se asignan objetos nuevos más allá de los valores que se deben cambiar.


Ruby 2.4 introdujo el método Hash#transform_values! que puedes usar

{ :a=>''a'' , :b=>''b'' }.transform_values! { |v| "%#{v}%" } # => {:a=>"%a%", :b=>"%b%"}


Si desea que las cadenas reales muten en su lugar (posiblemente y deseablemente afectando otras referencias a los mismos objetos de cadena):

# Two ways to achieve the same result (any Ruby version) my_hash.each{ |_,str| str.gsub! /^|$/, ''%'' } my_hash.each{ |_,str| str.replace "%#{str}%" }

Si desea que el hash cambie en su lugar, pero no desea afectar las cadenas (quiere que tenga nuevas cadenas):

# Two ways to achieve the same result (any Ruby version) my_hash.each{ |key,str| my_hash[key] = "%#{str}%" } my_hash.inject(my_hash){ |h,(k,str)| h[k]="%#{str}%"; h }

Si quieres un nuevo hash:

# Ruby 1.8.6+ new_hash = Hash[*my_hash.map{|k,str| [k,"%#{str}%"] }.flatten] # Ruby 1.8.7+ new_hash = Hash[my_hash.map{|k,str| [k,"%#{str}%"] } ]


Un método que no introduce efectos secundarios al original:

h = {:a => ''a'', :b => ''b''} h2 = Hash[h.map {|k,v| [k, ''%'' + v + ''%'']}]

Hash#map también puede ser una lectura interesante ya que explica por qué Hash.map no devuelve un hash (razón por la cual el conjunto resultante de pares de [key,value] se convierte en un nuevo hash) y proporciona enfoques alternativos al mismo patrón general.

Feliz codificación.

[Descargo de responsabilidad: no estoy seguro de si la semántica Hash.map cambia en Ruby 2.x]


Un poco más legible, map a una matriz de hashes de un solo elemento y reduce eso con merge

the_hash.map{ |key,value| {key => "%#{value}%"} }.reduce(:merge)


Hash.merge! es la solución más limpia

o = { a: ''a'', b: ''b'' } o.merge!(o) { |key, value| "%#{ value }%" } puts o.inspect > { :a => "%a%", :b => "%b%" }


my_hash.each do |key, value| my_hash[key] = "%#{value}%" end