Quel est le moyen (le plus rapide / le plus propre / le plus simple) de convertir toutes les clés d'un hachage de chaînes en symboles en Ruby?
Ce serait pratique lors de l'analyse de YAML.
my_hash = YAML.load_file('yml')
J'aimerais pouvoir utiliser:
my_hash[:key]
Plutôt que:
my_hash['key']
hash.symbolize_keys
ethash.deep_symbolize_keys
faites le travail si vous utilisez Rails.Réponses:
Dans Ruby> = 2.5 ( docs ), vous pouvez utiliser:
Vous utilisez une ancienne version de Ruby? Voici un one-liner qui copiera le hachage dans un nouveau avec les clés symbolisées:
Avec Rails, vous pouvez utiliser:
la source
each_with_object
comme ceci:my_hash.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
.tap
méthode pour supprimer le besoin de passermemo
à la fin. J'ai créé une version nettoyée de toutes les solutions (récursives également) gist.github.com/Integralist/9503099Voici une meilleure méthode, si vous utilisez Rails:
params. symbolize_keys
La fin.
Si vous ne l'êtes pas, il vous suffit de déchirer leur code (c'est aussi dans le lien):
la source
symbolize_keys
l'URL nouvelle et fonctionnelle (Rails 3). À l'origine, je viens de corriger l'URL deto_options
, mais il n'y a aucune documentation sur ce lien.symbolize_keys
a en fait une description, donc je l'ai utilisé à la place.hash.stringify_keys
.Pour le cas spécifique de YAML en Ruby, si les clés commencent par '
:
', elles seront automatiquement internées en tant que symboles.Production:
la source
YAML#load_file
par défaut toutes les clés sur des symboles au lieu de chaînes sans avoir à commencer chaque clé par deux points?Encore plus concis:
la source
my_hash.map { |k, v| [k.to_sym, v] }.to_h
si vous utilisez Rails, c'est beaucoup plus simple - vous pouvez utiliser un HashWithIndifferentAccess et accéder aux clés à la fois sous forme de chaîne et de symboles:
voir également:
http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html
Ou vous pouvez utiliser le génial "Facets of Ruby" Gem, qui contient beaucoup d'extensions aux classes Ruby Core et Standard Library.
voir aussi: http://rubyworks.github.io/rubyfaux/?doc=http://rubyworks.github.io/facets/docs/facets-2.9.3/core.json#api-class-Hash
la source
Puisque
Ruby 2.5.0
vous pouvez utiliserHash#transform_keys
ouHash#transform_keys!
.la source
stringify_keys
ousymbolize_keys
.http://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys
la source
Voici un moyen de symboliser profondément un objet
la source
J'aime vraiment le bijou Mash .
vous pouvez faire
mash['key']
, oumash[:key]
, oumash.key
la source
Si vous utilisez json et que vous souhaitez l'utiliser comme hachage, dans le noyau Ruby, vous pouvez le faire:
symbolize_names : si la valeur est true, renvoie les symboles des noms (clés) dans un objet JSON. Sinon, les chaînes sont retournées. Les chaînes sont la valeur par défaut.
Doc: Json # parse symbolize_names
la source
symbol_hash = JSON.parse(JSON.generate(YAML.safe_load(FILENAME)), symbolize_names: true)
est un moyen assez SEC (mais inefficace) d'obtenir rapidement un hachage avec des clés imbriquées comme symboles si elles proviennent d'un fichier YAML.params.symbolize_keys
fonctionnera également. Cette méthode transforme les clés de hachage en symboles et renvoie un nouveau hachage.la source
Une modification de la réponse @igorsales
la source
Dans Rails, vous pouvez utiliser:
Convertit en:
la source
deep_symbolize_keys
est ajouté dans l' extension Hash de Rails , mais il ne fait pas partie du noyau Ruby.Il y a tellement de réponses ici, mais la fonction des rails d'une méthode est
hash.symbolize_keys
la source
C'est ma seule doublure pour les hachages imbriqués
la source
Dans le cas où la raison pour laquelle vous devez le faire est que vos données proviennent à l'origine de JSON, vous pouvez ignorer l'une de ces analyses en passant simplement l'
:symbolize_names
option lors de l'ingestion de JSON.Aucun Rails requis et fonctionne avec Ruby> 1.9
la source
Vous pourriez être paresseux et l'envelopper dans un
lambda
:Mais cela ne fonctionnerait que pour lire à partir du hachage - pas pour écrire.
Pour ce faire, vous pouvez utiliser
Hash#merge
Le bloc init convertira les clés une fois sur demande, mais si vous mettez à jour la valeur de la version chaîne de la clé après avoir accédé à la version du symbole, la version du symbole ne sera pas mise à jour.
Vous pouvez également demander au bloc init de ne pas mettre à jour le hachage, ce qui vous protégerait de ce type d'erreur, mais vous seriez toujours vulnérable à l'inverse - la mise à jour de la version du symbole ne mettrait pas à jour la version de la chaîne:
Donc, la chose à laquelle il faut faire attention est de basculer entre les deux formes clés. Restez avec un.
la source
Souhaitez-vous quelque chose comme le travail suivant?
Cela copiera le hachage, mais vous ne vous en soucierez pas la plupart du temps. Il existe probablement un moyen de le faire sans copier toutes les données.
la source
un fwiw à une ligne plus court:
la source
Que dis-tu de ça:
la source
Ceci est destiné aux personnes qui utilisent
mruby
et n'ontsymbolize_keys
défini aucune méthode:La méthode:
String
RuntimeError
la source
!
danssymbolize_keys
. Sinon, ça marche bien.Le tableau que nous voulons changer.
strings = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
Créez une nouvelle variable sous forme de tableau vide afin que nous puissions ".push" les symboles dans.
symboles = []
Voici où nous définissons une méthode avec un bloc.
strings.each {| x | symboles.pousser (x.intern)}
Fin du code.
C'est donc probablement le moyen le plus simple de convertir des chaînes en symboles dans vos tableaux dans Ruby. Créez un tableau de chaînes, puis créez une nouvelle variable et définissez la variable sur un tableau vide. Sélectionnez ensuite chaque élément du premier tableau que vous avez créé avec la méthode ".each". Utilisez ensuite un code de bloc pour ".push" tous les éléments de votre nouveau tableau et utilisez ".intern ou .to_sym" pour convertir tous les éléments en symboles.
Les symboles sont plus rapides car ils économisent plus de mémoire dans votre code et vous ne pouvez les utiliser qu'une seule fois. Les symboles sont le plus souvent utilisés pour les clés de hachage, ce qui est génial. Je ne suis pas le meilleur programmeur ruby, mais cette forme de code m'a beaucoup aidé.Si quelqu'un connaît une meilleure façon de partager, vous pouvez également utiliser cette méthode pour le hachage!
la source
Si vous souhaitez une solution de rubis vanille et que moi, je n'ai pas accès
ActiveSupport
ici, c'est une solution de symbolisation profonde (très similaire aux précédentes)la source
À partir de Psych 3.0, vous pouvez ajouter l' option symbolize_names:
Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
Remarque: si vous avez une version Psych inférieure à 3.0,
symbolize_names:
elle sera silencieusement ignorée.Mon Ubuntu 18.04 l'inclut de la boîte avec ruby 2.5.1p57
la source
la source
a
entre crochets pour décomposer l'argument de bloc afin de rendre cela encore plus concis. Voir ma réponse par exemple.Ce n'est pas exactement une ligne, mais cela transforme toutes les clés de chaîne en symboles, également les imbriquées:
la source
J'aime ce one-liner, lorsque je n'utilise pas Rails, car je n'ai pas besoin de faire un deuxième hachage et de conserver deux ensembles de données pendant que je le traite:
Hash # delete renvoie la valeur de la clé supprimée
la source
Hash # deep_rekey de Facets est également une bonne option, en particulier:
Échantillon:
la source
En rubis, je trouve que c'est le moyen le plus simple et le plus facile à comprendre pour transformer les clés de chaîne en hachages en symboles:
Pour chaque clé du hachage, nous appelons la suppression, ce qui la supprime du hachage (la suppression renvoie également la valeur associée à la clé qui a été supprimée) et nous la définissons immédiatement égale à la clé symbolisée.
la source
Semblable aux solutions précédentes mais écrit un peu différemment.
Le code ne modifie pas le hachage transmis.
la source