在Ruby中更改散列中的每个值

我想改变散列中的每个值,以便在值的前后添加'%'

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

必须改成

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

什么是最好的方法来做到这一点?

如果你想让实际的string本身在适当的位置进行变异(可能并希望影响对相同string对象的其他引用):

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

如果你想要改变散列,但你不想影响string(你希望它得到新的string):

 # 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 } 

如果你想要一个新的哈希:

 # 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}%"] } ] 

在Ruby 2.1和更高版本中,你可以做

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

修改哈希值的最佳方法是

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

代码less,意图明确。 也更快,因为没有新的对象分配超出必须改变的值。

更可读一个, mapmap到一个单元哈希数组,并reduce merge

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

Ruby 2.4引入了方法Hash#transform_values! ,你可以使用。

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

一种不会对原件带来副作用的方法:

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

Hash#map也可能是一个有趣的读取,因为它解释了为什么Hash.map不返回Hash(这就是为什么[key,value]对的结果数组被转换为新的Hash),并提供了替代方法相同的一般模式。

快乐的编码。

[免责声明:我不确定在Ruby 2.x中Hash.map语义是否改变]

这个任务有一个新的“Rails方式”方法:) http://api.rubyonrails.org/classes/Hash.html#method-i-transform_values

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

Hash.merge! 是最干净的解决scheme

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

在用RSpectesting之后,像这样:

 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 

你可以像下面这样实现Hash#map_values:

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

该function可以像这样使用:

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