Лучший способ конвертировать строки в символы в хэше - PullRequest
231 голосов
/ 29 апреля 2009

Какой (самый быстрый / чистый / простой) способ преобразовать все ключи в хэше из строк в символы в Ruby?

Это было бы удобно при разборе YAML.

my_hash = YAML.load_file('yml')

Я бы хотел использовать:

my_hash[:key] 

Вместо:

my_hash['key']

Ответы [ 31 ]

296 голосов
/ 21 мая 2009

Вот лучший способ, если вы используете Rails:

PARAMS. symbolize_keys

Конец.

Если нет, просто сорвите их код (он также есть в ссылке):

myhash.keys.each do |key|
  myhash[(key.to_sym rescue key) || key] = myhash.delete(key)
end
211 голосов
/ 29 апреля 2009

Если вы хотите однострочник,

my_hash = my_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}

скопирует хэш в новый с символическими ключами.

113 голосов
/ 18 декабря 2009

Для конкретного случая YAML в Ruby, если ключи начинаются с ':', они будут автоматически интернированы как символы.

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
61 голосов
/ 10 апреля 2012

Еще более кратко:

Hash[my_hash.map{|(k,v)| [k.to_sym,v]}]
56 голосов
/ 27 августа 2011

если вы используете Rails, это намного проще - вы можете использовать HashWithIndifferentAccess и получать доступ к ключам как в виде строки, так и в виде символов:

my_hash.with_indifferent_access 

см. Также:

http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html


Или вы можете использовать удивительный Gem "Facets of Ruby", который содержит множество расширений для классов Ruby Core и Standard Library.

  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

40 голосов
/ 22 января 2018

С Ruby 2.5.0 вы можете использовать Hash#transform_keys или Hash#transform_keys!.

{'a' => 1, 'b' => 2}.transform_keys(&:to_sym) #=> {:a => 1, :b => 2}
31 голосов
/ 23 апреля 2014

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

hash = { 'name' => 'Rob', 'age' => '28' }
hash.symbolize_keys
# => { name: "Rob", age: "28" }
26 голосов
/ 03 августа 2012

Вот способ глубокой символизации объекта

def symbolize(obj)
    return obj.inject({}){|memo,(k,v)| memo[k.to_sym] =  symbolize(v); memo} if obj.is_a? Hash
    return obj.inject([]){|memo,v    | memo           << symbolize(v); memo} if obj.is_a? Array
    return obj
end
20 голосов
/ 21 мая 2009

Мне очень нравится Mash gem.

Вы можете сделать mash['key'], или mash[:key], или mash.key

12 голосов
/ 04 мая 2018

Если вы используете json и хотите использовать его как хеш, в ядре Ruby вы можете сделать это:

json_obj = JSON.parse(json_str, symbolize_names: true)

symbolize_names : если установлено значение true, возвращает символы для имен (ключей) в объекте JSON. В противном случае строки возвращаются. Строки по умолчанию.

Документ: Json # parse symbolize_names

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...