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

这在解析YAML时非常方便。

my_hash = YAML.load_file('yml')

我希望能够使用:

my_hash[:key] 

而不是:

my_hash['key']

当前回答

更简洁的是:

Hash[my_hash.map{|(k,v)| [k.to_sym,v]}]

其他回答

ruby-1.9.2-p180 :001 > h = {'aaa' => 1, 'bbb' => 2}
 => {"aaa"=>1, "bbb"=>2} 
ruby-1.9.2-p180 :002 > Hash[h.map{|a| [a.first.to_sym, a.last]}]
 => {:aaa=>1, :bbb=>2}

在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 

这是为那些使用mruby并且没有定义任何symbolize_keys方法的人准备的:

class Hash
  def symbolize_keys!
    self.keys.each do |k|
      if self[k].is_a? Hash
        self[k].symbolize_keys!
      end
      if k.is_a? String
        raise RuntimeError, "Symbolizing key '#{k}' means overwrite some data (key :#{k} exists)" if self[k.to_sym]
        self[k.to_sym] = self[k]
        self.delete(k)
      end
    end
    return self
  end
end

方法:

仅表示字符串类型的键 如果符号化字符串意味着丢失一些信息(覆盖哈希的一部分)将引发RuntimeError symbolic也是递归包含的散列 返回符号化的哈希值 工作到位!

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,这就简单多了——你可以使用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