Was ist die (schnellste / sauberste / unkomplizierteste) Möglichkeit, alle Schlüssel in einem Hash von Zeichenfolgen in Symbole in Ruby zu konvertieren?
Dies wäre praktisch, wenn Sie YAML analysieren.
my_hash = YAML.load_file('yml')
Ich möchte verwenden können:
my_hash[:key]
Eher, als:
my_hash['key']
hash.symbolize_keys
undhash.deep_symbolize_keys
erledigen Sie den Job, wenn Sie Rails verwenden.Antworten:
In Ruby> = 2.5 ( docs ) können Sie Folgendes verwenden:
Verwenden Sie eine ältere Ruby-Version? Hier ist ein Einzeiler, der den Hash mit den symbolisierten Schlüsseln in einen neuen kopiert:
Mit Rails können Sie verwenden:
quelle
each_with_object
wiemy_hash.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
.tap
Methode auch verwenden , um die Notwendigkeit zu beseitigen,memo
am Ende zu bestehen. Ich habe eine bereinigte Version aller Lösungen (auch rekursive) erstellt. Gist.github.com/Integralist/9503099Hier ist eine bessere Methode, wenn Sie Rails verwenden:
params. symbolize_keys
Das Ende.
Wenn Sie nicht sind, rippen Sie einfach ihren Code ab (es ist auch im Link):
quelle
symbolize_keys
mit der neuen & funktionierenden (Rails 3) URL umgestellt . Ich habe ursprünglich nur die URL für festgelegtto_options
, aber unter diesem Link befindet sich keine Dokumentation.symbolize_keys
hat tatsächlich eine Beschreibung, also habe ich diese stattdessen verwendet.hash.stringify_keys
funktioniert.Für den speziellen Fall von YAML in Ruby, wenn die Schlüssel mit 'beginnen
:
' , werden sie automatisch als Symbole interniert.Ausgabe:
quelle
YAML#load_file
alle Schlüssel auf Symbole als Standard festzulegen, anstatt Zeichenfolgen, ohne dass jede Taste mit einem Doppelpunkt beginnen muss?Noch knapper:
quelle
my_hash.map { |k, v| [k.to_sym, v] }.to_h
Wenn Sie Rails verwenden, ist dies viel einfacher. Sie können einen HashWithIndifferentAccess verwenden und auf die Schlüssel sowohl als String als auch als Symbole zugreifen:
siehe auch:
http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html
Oder Sie können den fantastischen Edelstein "Facets of Ruby" verwenden, der viele Erweiterungen für Ruby Core- und Standard Library-Klassen enthält.
Siehe auch: http://rubyworks.github.io/rubyfaux/?doc=http://rubyworks.github.io/facets/docs/facets-2.9.3/core.json#api-class-Hash
quelle
Da können
Ruby 2.5.0
SieHash#transform_keys
oder verwendenHash#transform_keys!
.quelle
stringify_keys
oder gibtsymbolize_keys
.http://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys
quelle
Hier ist eine Möglichkeit, ein Objekt tief zu symbolisieren
quelle
Ich mag das Mash- Juwel wirklich .
Sie können tun
mash['key']
, odermash[:key]
, odermash.key
quelle
Wenn Sie json verwenden und es als Hash verwenden möchten, können Sie dies in Core Ruby tun:
symbolize_names : Wenn auf true gesetzt, werden Symbole für die Namen (Schlüssel) in einem JSON-Objekt zurückgegeben. Andernfalls werden Zeichenfolgen zurückgegeben. Zeichenfolgen sind die Standardeinstellung.
Doc: Json # parse symbolize_names
quelle
symbol_hash = JSON.parse(JSON.generate(YAML.safe_load(FILENAME)), symbolize_names: true)
ist eine ziemlich trockene (aber ineffiziente) Möglichkeit, schnell einen Hash mit verschachtelten Schlüsseln als Symbol zu erhalten, wenn er aus einer YAML-Datei stammt.params.symbolize_keys
wird auch funktionieren. Diese Methode wandelt Hash-Schlüssel in Symbole um und gibt einen neuen Hash zurück.quelle
Eine Änderung an @igorsales Antwort
quelle
In Rails können Sie verwenden:
Konvertiert zu:
quelle
deep_symbolize_keys
wird in der Hash- Erweiterung von Rails hinzugefügt , ist jedoch nicht Teil des Ruby-Kerns.So viele Antworten hier, aber die eine Methode Schienenfunktion ist
hash.symbolize_keys
quelle
Dies ist mein Einzeiler für verschachtelte Hashes
quelle
Falls der Grund , warum Sie dies tun müssen, darin besteht, dass Ihre Daten ursprünglich von JSON stammen, können Sie jede dieser Analysen überspringen, indem Sie einfach die übergeben
:symbolize_names
Option auf die Einnahme von JSON.Keine Rails erforderlich und funktioniert mit Ruby> 1.9
quelle
Sie könnten faul sein und es einwickeln in
lambda
:Dies würde jedoch nur zum Lesen aus dem Hash funktionieren - nicht zum Schreiben.
Um das zu tun, könnten Sie verwenden
Hash#merge
Der Init-Block konvertiert die Schlüssel bei Bedarf einmal. Wenn Sie jedoch den Wert für die Zeichenfolgenversion des Schlüssels nach dem Zugriff auf die Symbolversion aktualisieren, wird die Symbolversion nicht aktualisiert.
Sie könnten auch den Init-Block veranlassen, den Hash nicht zu aktualisieren, was Sie vor dieser Art von Fehler schützen würde, aber Sie wären immer noch anfällig für das Gegenteil - das Aktualisieren der Symbolversion würde die String-Version nicht aktualisieren:
Bei diesen ist es also wichtig, zwischen den beiden Schlüsselformen zu wechseln. Bleib bei einem.
quelle
Würde so etwas wie folgendes funktionieren?
Es wird den Hash kopieren, aber das wird Sie die meiste Zeit nicht interessieren. Es gibt wahrscheinlich eine Möglichkeit, dies zu tun, ohne alle Daten zu kopieren.
quelle
ein kürzerer Einzeiler fwiw:
quelle
Wie wäre es damit:
quelle
Dies ist für Personen gedacht
mruby
, die einesymbolize_keys
Methode verwenden und nicht definiert haben:Die Methode:
String
RuntimeError
quelle
!
in vergessensymbolize_keys
. Ansonsten funktioniert gut.Das Array, das wir ändern möchten.
string = ["HTML", "CSS", "JavaScript", "Python", "Ruby"]
Machen Sie eine neue Variable als leeres Array, damit wir die Symbole in ".push" können.
Symbole = []
Hier definieren wir eine Methode mit einem Block.
string.each {| x | symbols.push (x.intern)}
Ende des Codes.
Dies ist wahrscheinlich die einfachste Möglichkeit, Zeichenfolgen in Symbole in Ihren Arrays in Ruby zu konvertieren. Erstellen Sie ein Array von Zeichenfolgen, erstellen Sie dann eine neue Variable und setzen Sie die Variable auf ein leeres Array. Wählen Sie dann jedes Element im ersten Array aus, das Sie mit der Methode ".each" erstellt haben. Verwenden Sie dann einen Blockcode, um alle Elemente in Ihrem neuen Array zu "pushen", und konvertieren Sie alle Elemente mit ".intern oder .to_sym" in Symbole.
Symbole sind schneller, weil sie mehr Speicherplatz in Ihrem Code sparen und Sie sie nur einmal verwenden können. Symbole werden am häufigsten für Schlüssel in Hash verwendet, was großartig ist. Ich bin nicht der beste Ruby-Programmierer, aber diese Art von Code hat mir sehr geholfen. Wenn jemand einen besseren Weg kennt, teilen Sie ihn bitte mit, und Sie können diese Methode auch für Hash verwenden!
quelle
Wenn Sie Vanille-Rubin-Lösung möchten und da ich keinen Zugang zu
ActiveSupport
hier habe, ist tief symbolisieren Lösung (sehr ähnlich zu vorherigen)quelle
Ab Psych 3.0 können Sie die Option symbolize_names: hinzufügen
Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
Hinweis: Wenn Sie eine niedrigere Psych-Version als 3.0 haben,
symbolize_names:
wird diese stillschweigend ignoriert.Mein Ubuntu 18.04 enthält es sofort mit Ruby 2.5.1p57
quelle
quelle
a
in Klammern setzen, um das Blockargument zu zerlegen und es noch knapper zu machen. Siehe meine Antwort zum Beispiel.Dies ist nicht gerade ein Einzeiler, aber es verwandelt alle Zeichenfolgenschlüssel in Symbole, auch die verschachtelten:
quelle
Ich mag diesen Einzeiler, wenn ich Rails nicht verwende, weil ich dann keinen zweiten Hash erstellen und zwei Datensätze speichern muss, während ich ihn verarbeite:
Hash # delete gibt den Wert des gelöschten Schlüssels zurück
quelle
Facets 'Hash # deep_rekey ist auch eine gute Option, insbesondere:
Stichprobe:
quelle
In Ruby finde ich, dass dies die einfachste und verständlichste Methode ist, um String-Schlüssel in Hashes in Symbole umzuwandeln:
Für jeden Schlüssel im Hash rufen wir delete auf, wodurch er aus dem Hash entfernt wird (auch delete gibt den Wert zurück, der dem gelöschten Schlüssel zugeordnet ist ), und wir setzen diesen sofort gleich dem symbolisierten Schlüssel.
quelle
Ähnlich wie bei früheren Lösungen, jedoch etwas anders geschrieben.
Der Code mutiert den übergebenen Hash nicht.
quelle