Comment puis-je convertir un Rubis de hachage, de sorte que l'ensemble de ses touches sont des symboles?
J'ai un Rubis de hachage qui ressemble à:
{ "id" => "123", "name" => "test" }
Je voudrais le convertir en:
{ :id => "123", :name => "test" }
- dup?
- La récursivité!
- Une autre option consiste à utilisons la
HashWithIndifferentAccess
. Ensuite, vous n'aurez jamais à vous soucier de la conversion de la table de hachage, vous pouvez utiliser un symbole pour récupérer une valeur, même si certaines touches sont insérés comme des chaînes de caractères. Si vous n'êtes pas à l'aide de Rails, alors vous aurez àinclude 'active_support/core_ext/hash/indifferent_access'
.
Vous devez vous connecter pour publier un commentaire.
Mise à jour:
@mu est trop court: Ne pas voir le mot "récursif", mais si vous insistez (avec protection contre inexistante
to_sym
, je veux juste vous rappeler qu'en Ruby 1.81.to_sym == nil
, donc, en jouant avec certains types de clés peut être trompeuse):to_sym
. Vous pourriez avoir demandé une version récursive si.Si vous arrive d'être dans les Rails, alors vous aurez
symbolize_keys
:et
symbolize_keys!
qui fait la même chose, mais opère en place. Donc, si vous êtes dans les Rails, vous pouvez:Si vous souhaitez de manière récursive symbolisent intérieure hachages alors je pense que vous avez à faire vous-même, mais avec quelque chose comme ceci:
Vous pourriez vouloir jouer avec le
kind_of? Hash
pour correspondre à votre situation spécifique; l'utilisation derespond_to? :keys
pourrait faire plus de sens. Et si vous souhaitez autoriser pour les touches qui ne comprennent pasto_sym
, puis:Noter que
h[ks] = h.delete k
ne change pas le contenu de la table de Hachage lors dek == ks
mais il permettra de préserver l'ordre lorsque vous êtes à l'aide de Ruby 1.9+. Vous pouvez également utiliser la[(key.to_sym rescue key) || key]
approche Rails utilise dans leursymbolize_keys!
mais je pense que c'est un abus du système de gestion des exceptions.La deuxième
symbolize_keys_deep!
transforme ce:dans cette:
Vous pourriez monkey patch soit la version de
symbolize_keys_deep!
dans Hachage si tu le voulais vraiment, mais j'ai généralement de rester loin de monkey patching, à moins que j'ai de très bonnes raisons de le faire.deep_symbolize_keys
: api.rubyonrails.org/classes/...ActionController::Parameters
plus hérite de hachage. L'utilisation de ce comportement obsolète expose les problèmes de sécurité potentiels. Si vous continuez à utiliser cette méthode, vous pouvez créer une faille de sécurité dans votre application qui peuvent être exploitées. Au lieu de cela, pensez à utiliser une de ces méthodes documentées et qui ne sont pas obsolètes: api.rubyonrails.org/v5.0.0.1/classes/ActionController/...params.symbolize_keys
(d'où leActionController::Parameters
), je ne vois aucune preuve queHash#symbolize_keys
est obsolète juste queparams.is_a? Hash
ne sera pas vrai dans 5.1.Si vous êtes à l'aide de Rails >= 4, vous pouvez utiliser:
ou
voir http://apidock.com/rails/v4.2.1/Hash/deep_symbolize_keys
Juste au cas où vous êtes parsing JSON, de la json docs vous pouvez ajouter l'option pour symboliser les clés lors de l'analyse:
hash = JSON.parse(hash.to_json, symbolize_names: true)
.Victor Moroz fourni une belle réponse pour la simple récursive cas, mais il ne sera pas procédé de hachages sont imbriquées à l'intérieur des tableaux imbriqués:
Si vous avez besoin de soutien hachages dans des tableaux au sein de tables de hachage, vous aurez envie de quelque chose de plus comme ceci:
Essayez ceci:
Ce itère sur les touches, et pour chacun, il supprime le stringified touche et affecte sa valeur à la symbolisé clé.
h.keys
), qui est un peu déroutant. J'ai utilisé #appuyez sur pour que le résultat est la valeur de hachage plutôt que de la matrice de touches. C'est juste pour illustrer.Si vous êtes à l'aide de Rails (ou juste activesupport):
symbolize_keys
n'est pas récursive.Ruby one-liner qui est plus rapide que la réponse choisie
Les résultats d'un Benchmark
k.intern
bien venu? Votre extrait de code ne fonctionne pas à cause de cela et parce que je ne suis pas un pro Ruby-er l'extrait est tellement efficace qu'il est difficile de donner un sens.String.intern
méthode. Il a échoué pour moi parce que c'était de l'exécution de l'k.intern
propriété sur unsymbol
à la place. ruby-doc.org/core-2.2.0/String.html#method-i-internDe commencer avec Ruby 2.5, vous pouvez utiliser
transform_key
méthode: https://docs.ruby-lang.org/en/trunk/Hash.html#method-i-transform_keysDonc dans votre cas serait:
Remarque: les mêmes méthodes sont également disponibles sur Ruby on Rails.
Je suis partie à l':
Cela fonctionne parce que nous sommes une itération sur les valeurs de hachage et en construire un nouveau à la volée. Il n'est pas récursive, mais vous pouvez comprendre cela de regarder quelques-unes des autres réponses.
each_with_object
serait sans doute mieux appeler queinject
dans ce cas (à moins bien sûreach_with_object
n'était pas disponible).inject
, juste parce que je l'utilise toujours. En regardant la source de les deux,inject
est plus grand, mais cela ne signifie pas nécessairement plus lent, ou ralentir assez pour faire une réelle différence. L'inversion de paramètres et à l'absence de nécessité d'un retourh
va provoquer une pause dans ma façon de penser à l'utiliser, est-il une raison impérieuse d'utilisereach_with_object
? Peut-être que certains de référence quelque part en montrantinject
arriver fumé?inject
lorsque je suis intéressé par le bloc de valeur de retour (a.inject(:+)
) eteach_with_object
quand j'aurais à ajouter les; h
peu pour le bloc ou quand je suis intéressants dans "itération avec quelques bagages" plutôt que sur une simple injection. Le bloc argument afin de différence entre eux est un peu pervers. Je trouve que le bloc de valeur de retour devient visuellement perdu plus dans le côté droit. Ou peut-être que je suis juste opiniâtre 🙂Vous pouvez également étendre la base de Hachage classe ruby placer un /lib/hachage.rb fichier :
Si vous voulez vous assurer que les clés de hachage enveloppé dans des tableaux à l'intérieur de votre parent de hachage sont symbolisées, vous avez besoin d'étendre la classe array création d'un tableau.rb" fichier avec le code :
Cela permet d'appeler des "symbolize_keys_deep!" à tout de hachage variable comme ceci :
Voici mes deux cents,
ma version de
symbolize_keys_deep!
utilise l'original symbolize_keys! fournis par les rails et fait juste un simple appel récursif pour Symboliser sous les tables de hachage.Facettes' Hash#remise à la clé est également digne de mention.
Exemple:
Il y a aussi une version récursive:
Voici une petite fonction récursive en profondeur la symbolisation de l'clés: