如何更改哈希值?

时间:2009-05-01 18:17:46

标签: ruby syntax hash

我想用value替换散列中的每个value.some_method

例如,给定一个简单的哈希:

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

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

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

我尝试了#collect#map,但总是只是让数组回来。是否有一种优雅的方式来做到这一点?

更新

该死的,我忘记了:哈希是一个不应该改变的实例变量。我需要一个带有更改值的新哈希,但是不希望显式定义该变量,然后遍历填充它的哈希。类似的东西:

new_hash = hash.magic{ ... }

11 个答案:

答案 0 :(得分:201)

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 } 

最后一个版本还有一个额外的好处,你也可以转换键。

答案 1 :(得分:76)

由于 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!版本。

答案 2 :(得分:32)

您可以收集这些值,然后再将它从Array转换为Hash。

像这样:

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

答案 3 :(得分:22)

这样做:

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

inject相反,优点是你不需要在块内再次返回哈希值。

答案 4 :(得分:10)

尝试此功能:

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

答案 5 :(得分:9)

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

由于他们使用each进行操作,我认为没有比循环更好的方法了。

hash = {sample: 'gach'}

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

<强>更新

从Ruby 2.4.0开始,您可以原生使用#transform_values#transform_values!

答案 6 :(得分:1)

我这样做:

  

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

这为您提供了通过任何表达式转换键或值的功能(当然,它也是非破坏性的)。

答案 7 :(得分:1)

您可能希望更进一步,在嵌套哈希上执行此操作。当然,这与Rails项目相当。

这里有一些代码可以确保params哈希是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  

答案 8 :(得分:1)

Ruby有tap方法(1.8.71.9.32.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"}

答案 9 :(得分:1)

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

答案 10 :(得分:0)

<强> Rails的特定

如果有人只需要为每个值调用to_s方法并且不使用Rails 4.2(包括transform_values方法link),您可以执行以下操作: / p>

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:这也会将密钥转换为字符串