¿Cuál es la forma (más rápida / más limpia / directa) de convertir todas las claves en un hash de cadenas a símbolos en Ruby?
Esto sería útil al analizar YAML.
my_hash = YAML.load_file('yml')
Me gustaría poder usar:
my_hash[:key]
Más bien que:
my_hash['key']
hash.symbolize_keys
yhash.deep_symbolize_keys
haz el trabajo si estás usando Rails.Respuestas:
En Ruby> = 2.5 ( docs ) puede usar:
¿Usa una versión anterior de Ruby? Aquí hay una línea que copiará el hash en uno nuevo con las teclas simbolizadas:
Con Rails puedes usar:
fuente
each_with_object
así:my_hash.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
.tap
método para eliminar la necesidad de aprobarmemo
al final. He creado una versión limpia de todas las soluciones (también las recursivas) gist.github.com/Integralist/9503099Aquí hay un método mejor, si está utilizando Rails:
params simbolizar_claves
El fin.
Si no lo está, simplemente copie su código (también está en el enlace):
fuente
symbolize_keys
la nueva y funcional URL (Rails 3). Originalmente solo arreglé la URL parato_options
, pero no hay documentación en ese enlace.symbolize_keys
en realidad tiene una descripción, así que la usé en su lugar.hash.stringify_keys
funciona.Para el caso específico de YAML en Ruby, si las teclas comienzan con '
:
', serán internados automáticamente como símbolos.Salida:
fuente
YAML#load_file
por defecto todas las teclas de símbolos en lugar de cadenas sin tener que comenzar cada tecla con dos puntos?Aún más conciso:
fuente
my_hash.map { |k, v| [k.to_sym, v] }.to_h
si usa Rails, es mucho más simple: puede usar un acceso HashWithIndifferentAccess y acceder a las teclas como String y Symbols:
ver también:
http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html
O puede usar la increíble Gema "Facetas de Ruby", que contiene muchas extensiones para las clases Ruby Core y Standard Library.
ver también: http://rubyworks.github.io/rubyfaux/?doc=http://rubyworks.github.io/facets/docs/facets-2.9.3/core.json#api-class-Hash
fuente
Ya
Ruby 2.5.0
que puedes usarHash#transform_keys
oHash#transform_keys!
.fuente
stringify_keys
osymbolize_keys
.http://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys
fuente
Aquí hay una manera de simbolizar profundamente un objeto
fuente
Realmente me gusta la gema Mash .
puedes hacer
mash['key']
, omash[:key]
, omash.key
fuente
Si está utilizando json y desea utilizarlo como hash, en el núcleo de Ruby puede hacerlo:
symbolize_names : si se establece en true, devuelve símbolos para los nombres (claves) en un objeto JSON. De lo contrario, se devuelven las cadenas. Las cadenas son las predeterminadas.
Doc: Json # parse symbolize_names
fuente
symbol_hash = JSON.parse(JSON.generate(YAML.safe_load(FILENAME)), symbolize_names: true)
es una forma bastante SECA (pero ineficiente) de obtener rápidamente un hash con claves anidadas como símbolos si proviene de un archivo YAML.params.symbolize_keys
También funcionará. Este método convierte las claves hash en símbolos y devuelve un nuevo hash.fuente
Una modificación a la respuesta @igorsales
fuente
En Rails puedes usar:
Convierte a:
fuente
deep_symbolize_keys
se agrega en la extensión Hash de Rails , pero no es parte del núcleo de Ruby.Tantas respuestas aquí, pero la función de un método rails es
hash.symbolize_keys
fuente
Este es mi único forro para hashes anidados
fuente
En caso de que la razón por la que tiene que hacer esto es porque los datos originalmente vinieron de JSON, puede omitir cualquiera de este análisis, mediante el simple en el
:symbolize_names
opción al ingerir JSON.No se requieren rieles y funciona con Ruby> 1.9
fuente
Podrías ser flojo y envolverlo en
lambda
:Pero esto solo funcionaría para leer desde el hash, no para escribir.
Para hacer eso, podrías usar
Hash#merge
El bloque init convertirá las claves una vez a pedido, aunque si actualiza el valor para la versión de cadena de la clave después de acceder a la versión del símbolo, la versión del símbolo no se actualizará.
También podría hacer que el bloque de inicio no actualice el hash, lo que lo protegería de ese tipo de error, pero aún sería vulnerable a lo contrario: actualizar la versión del símbolo no actualizaría la versión de la cadena:
Entonces, lo que hay que tener cuidado con esto es cambiar entre las dos formas clave. Quédate con uno.
fuente
¿Algo como el siguiente trabajo?
Copiará el hash, pero eso no te importará la mayor parte del tiempo. Probablemente haya una manera de hacerlo sin copiar todos los datos.
fuente
un fwiw de una línea más corto:
fuente
Qué tal esto:
fuente
Esto es para personas que usan
mruby
y no tienen ningúnsymbolize_keys
método definido:El método:
String
RuntimeError
fuente
!
insymbolize_keys
. De lo contrario funciona bien.La matriz que queremos cambiar.
cadenas = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
Haga una nueva variable como una matriz vacía para que podamos "empujar" los símbolos.
símbolos = []
Aquí es donde definimos un método con un bloque.
strings.each {| x | símbolos.push (x.intern)}
Fin del código.
Por lo tanto, esta es probablemente la forma más sencilla de convertir cadenas en símbolos en su (s) matriz (s) en Ruby. Haga una matriz de cadenas, luego haga una nueva variable y establezca la variable en una matriz vacía. Luego seleccione cada elemento en la primera matriz que creó con el método ".each". Luego use un código de bloque para ".push" todos los elementos en su nueva matriz y use ".intern o .to_sym" para convertir todos los elementos en símbolos.
Los símbolos son más rápidos porque ahorran más memoria dentro de su código y solo puede usarlos una vez. Los símbolos se usan más comúnmente para claves en hash, lo cual es genial. No soy el mejor programador de ruby, pero esta forma de código me ayudó mucho. ¡Si alguien conoce una mejor manera, por favor comparte y puedes usar este método para el hash también!
fuente
Si desea una solución de vainilla rubí y como yo no tengo acceso
ActiveSupport
aquí, es una solución de simbolización profunda (muy similar a las anteriores)fuente
A partir de Psych 3.0, puede agregar la opción symbolize_names:
Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
Nota: si tiene una versión de Psych inferior a la 3.0
symbolize_names:
, se ignorará en silencio.Mi Ubuntu 18.04 lo incluye listo para usar con ruby 2.5.1p57
fuente
fuente
a
entre paréntesis para descomponer el argumento de bloque para hacerlo aún más conciso. Vea mi respuesta por ejemplo.Esto no es exactamente una línea, pero convierte todas las teclas de cadena en símbolos, también las anidadas:
fuente
Me gusta esta frase, cuando no estoy usando Rails, porque entonces no tengo que hacer un segundo hash y mantener dos conjuntos de datos mientras lo estoy procesando:
Hash # delete devuelve el valor de la clave eliminada
fuente
Facets 'Hash # deep_rekey también es una buena opción, especialmente:
Muestra:
fuente
En ruby, encuentro que esta es la forma más simple y fácil de entender para convertir las teclas de cadena en hashes a símbolos:
Para cada clave en el hash llamamos eliminar en él que lo elimina del hash (también eliminar devuelve el valor asociado con la clave que se eliminó) e inmediatamente establecemos esto igual a la clave simbolizada.
fuente
Similar a las soluciones anteriores, pero escrito de manera un poco diferente.
El código no muta el hash pasado.
fuente