在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)

其他回答

这是嵌套哈希的一行代码

def symbolize_keys(hash)
  hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v.is_a?(Hash) ? symbolize_keys(v) : v }
end

在Rails中,你可以使用:

{'g'=> 'a', 2 => {'v' => 'b', 'x' => { 'z' => 'c'}}}.deep_symbolize_keys!

转换:

{:g=>"a", 2=>{:v=>"b", :x=>{:z=>"c"}}}

facet的Hash#deep_rekey也是一个不错的选择,特别是:

如果你在项目中发现了其他糖的用途, 如果您更喜欢代码可读性而不是神秘的一行程序。

示例:

require 'facets/hash/deep_rekey'
my_hash = YAML.load_file('yml').deep_rekey

对于Ruby中YAML的特定情况,如果键以':'开头,它们将被自动作为符号存储。

require 'yaml'
require 'pp'
yaml_str = "
connections:
  - host: host1.example.com
    port: 10000
  - host: host2.example.com
    port: 20000
"
yaml_sym = "
:connections:
  - :host: host1.example.com
    :port: 10000
  - :host: host2.example.com
    :port: 20000
"
pp yaml_str = YAML.load(yaml_str)
puts yaml_str.keys.first.class
pp yaml_sym = YAML.load(yaml_sym)
puts yaml_sym.keys.first.class

输出:

#  /opt/ruby-1.8.6-p287/bin/ruby ~/test.rb
{"connections"=>
  [{"port"=>10000, "host"=>"host1.example.com"},
   {"port"=>20000, "host"=>"host2.example.com"}]}
String
{:connections=>
  [{:port=>10000, :host=>"host1.example.com"},
   {:port=>20000, :host=>"host2.example.com"}]}
Symbol

类似于前面的解决方案,但写得有点不同。

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