我想用value
替换散列中的每个value.some_method
。
例如,给定一个简单的哈希:
{"a" => "b", "c" => "d"}`
每个值都应为.upcase
d,所以它看起来像:
{"a" => "B", "c" => "D"}
我尝试了#collect
和#map
,但总是只是让数组回来。是否有一种优雅的方式来做到这一点?
更新
该死的,我忘记了:哈希是一个不应该改变的实例变量。我需要一个带有更改值的新哈希,但是不希望显式定义该变量,然后遍历填充它的哈希。类似的东西:
new_hash = hash.magic{ ... }
答案 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.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"}
答案 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:这也会将密钥转换为字符串