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

这在解析YAML时非常方便。

my_hash = YAML.load_file('yml')

我希望能够使用:

my_hash[:key] 

而不是:

my_hash['key']

当前回答

如果你想要香草红宝石解决方案,因为我没有访问ActiveSupport这里是深符号解决方案(非常类似于以前的)

    def deep_convert(element)
      return element.collect { |e| deep_convert(e) } if element.is_a?(Array)
      return element.inject({}) { |sh,(k,v)| sh[k.to_sym] = deep_convert(v); sh } if element.is_a?(Hash)
      element
    end

其他回答

这是嵌套哈希的一行代码

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

在ruby中,我发现这是最简单、最容易理解的将字符串键转换为符号的方法:

my_hash.keys.each { |key| my_hash[key.to_sym] = my_hash.delete(key)}

对于散列中的每个键,我们调用delete函数将其从散列中删除(delete也返回与被删除的键相关的值),并立即将其设置为符号化的键。

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

会像下面这样工作吗?

new_hash = Hash.new
my_hash.each { |k, v| new_hash[k.to_sym] = v }

它会复制哈希值,但大多数时候你不会在意。可能有一种不复制所有数据的方法。