在Ruby中,将哈希中的所有键从字符串转换为符号的(最快/最干净/直接)方法是什么?
这在解析YAML时非常方便。
my_hash = YAML.load_file('yml')
我希望能够使用:
my_hash[:key]
而不是:
my_hash['key']
在Ruby中,将哈希中的所有键从字符串转换为符号的(最快/最干净/直接)方法是什么?
这在解析YAML时非常方便。
my_hash = YAML.load_file('yml')
我希望能够使用:
my_hash[:key]
而不是:
my_hash['key']
当前回答
如果您需要这样做的原因是因为您的数据最初来自JSON,那么您可以跳过任何解析,只需在摄取JSON时传入:symbolize_names选项即可。
不需要Rails和工作与Ruby >1.9
JSON.parse(my_json, :symbolize_names => true)
其他回答
在Ruby >= 2.5 (docs)中,你可以使用:
my_hash.transform_keys(&:to_sym)
使用旧的Ruby版本?下面是一个单行程序,它将哈希复制到一个新的哈希中,并将键符号化:
my_hash = my_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
使用Rails,您可以使用:
my_hash.symbolize_keys
my_hash.deep_symbolize_keys
Symbolize_keys递归为任何哈希:
class Hash
def symbolize_keys
self.is_a?(Hash) ? Hash[ self.map { |k,v| [k.respond_to?(:to_sym) ? k.to_sym : k, v.is_a?(Hash) ? v.symbolize_keys : v] } ] : self
end
end
@igorsales answer的修改
class Object
def deep_symbolize_keys
return self.inject({}){|memo,(k,v)| memo[k.to_sym] = v.deep_symbolize_keys; memo} if self.is_a? Hash
return self.inject([]){|memo,v | memo << v.deep_symbolize_keys; memo} if self.is_a? Array
return self
end
end
如果你使用的是Rails,这就简单多了——你可以使用HashWithIndifferentAccess,并以字符串和符号的形式访问键:
my_hash.with_indifferent_access
参见:
http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html
或者你可以使用很棒的“Facets of Ruby”Gem,它包含了很多对Ruby核心和标准库类的扩展。
require 'facets'
> {'some' => 'thing', 'foo' => 'bar'}.symbolize_keys
=> {:some=>"thing", :foo=>"bar}
参见: http://rubyworks.github.io/rubyfaux/?doc=http://rubyworks.github.io/facets/docs/facets-2.9.3/core.json#api-class-Hash
类似于前面的解决方案,但写得有点不同。
This allows for a hash that is nested and/or has arrays. Get conversion of keys to a string as a bonus. Code does not mutate the hash been passed in. module HashUtils def symbolize_keys(hash) transformer_function = ->(key) { key.to_sym } transform_keys(hash, transformer_function) end def stringify_keys(hash) transformer_function = ->(key) { key.to_s } transform_keys(hash, transformer_function) end def transform_keys(obj, transformer_function) case obj when Array obj.map{|value| transform_keys(value, transformer_function)} when Hash obj.each_with_object({}) do |(key, value), hash| hash[transformer_function.call(key)] = transform_keys(value, transformer_function) end else obj end end end