如何改变哈希值?

我想用value.some_methodreplace散列中的每个value

例如,给定一个简单的散列:

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

每个值应该是.upcase d,所以它看起来像:

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

我试过#collect#map但总是把数组取回来。 有没有一个优雅的方式来做到这一点?

UPDATE

该死的,我忘了:哈希是在一个实例variables,不应该改变。 我需要一个新的哈希与更改的值,但不希望明确定义该variables,然后遍历哈希填充它。 就像是:

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

或者,如果您希望以非破坏方式执行此操作,并返回一个新的散列而不是修改my_hash

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

这最后一个版本还有另外一个好处,就是你可以转换密钥。

您可以收集这些值,并将其从Array再次转换为哈希值。

喜欢这个:

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

这将做到这一点:

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

inject优势相反的是,你不需要在块内再次返回散列。

由于ruby 2.4.0你可以使用本地Hash#transform_values方法:

 hash = {"a" => "b", "c" => "d"} new_hash = hash.transform_values(&:upcase) # => {"a" => "B", "c" => "D"} 

还有破坏性的Hash#transform_values! 版。

试试这个function:

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

ActiveSupport v4.2.0中有一个方法。 它被称为transform_values ,基本上只是为每个键值对执行一个块。

既然他们each都这样做,我觉得没有比循环更好的方法了。

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

我做这样的事情:

new_hash = Hash [* original_hash.collect {| key,value | [key,value + 1]}。flatten]

这为您提供了通过任何expression式来转换键或值的function(当然,这也是非破坏性的)。

您可能想要更进一步,并在嵌套散列上执行此操作。 当然,这发生在Rails项目中。

这里有一些代码来确保参数哈希是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 

Ruby有tap方法( 1.8.7,1.9.3和2.1.0 ),对于像这样的东西非常有用。

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

如果您知道这些值是string,则可以在循环中调用它们的replace方法:这样您将更改该值。

Altohugh这仅限于价值是string的情况,因此不能完全回答这个问题,我认为这可能对某人有用。

Rails的具体

如果有人只需要为每个值调用to_s方法,并且不使用Rails 4.2(其中包含transform_values方法链接 ),则可以执行以下操作:

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

注意:使用'json'库是必需的。

注2:这也将钥匙变成string