在Ruby中,将哈希中的所有键从字符串转换为符号的(最快/最干净/直接)方法是什么?

这在解析YAML时非常方便。

my_hash = YAML.load_file('yml')

我希望能够使用:

my_hash[:key] 

而不是:

my_hash['key']

当前回答

参数个数。Symbolize_keys也可以工作。这个方法将哈希键转换为符号并返回一个新的哈希值。

其他回答

http://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys

hash = { 'name' => 'Rob', 'age' => '28' }
hash.symbolize_keys
# => { name: "Rob", age: "28" }

对于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

从Psych 3.0开始,你可以添加symbolize_names:选项

心理。加载("——\n foo: bar") # => {"foo"=>"bar"}

心理。加载("——\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}

注意:如果你的Psych版本低于3.0,symbolize_names:将被默默地忽略。

我的Ubuntu 18.04自带ruby 2.5.1p57

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

如果你在使用Rails,这里有一个更好的方法:

params.symbolize_keys

最后。

如果你不是,那就抄袭他们的代码(链接中也有):

myhash.keys.each do |key|
  myhash[(key.to_sym rescue key) || key] = myhash.delete(key)
end