Hängen Sie das Schlüssel / Wert-Paar mit << in Ruby an den Hash an


80

In Ruby können Werte mit <<: an vorhandene Arrays angehängt werden:

a = []
a << "foo"

Können Sie aber auch Schlüssel / Wert-Paare an einen vorhandenen Hash anhängen?

h = {}
h << :key "bar"

Ich weiß, dass Sie Folgendes tun können:

h[:key] = ""
h[:key] << "bar"

aber das will ich nicht.

Vielen Dank.


20
Warum nicht h[:key] = "bar"?
Hauleth

4
Das funktioniert nicht:h[:key] << "bar"
Chris Nielsen

Antworten:


141

Es gibt merge!.

h = {}
h.merge!(key: "bar")
# => {:key=>"bar"}

3
Ich glaube nicht, dass man merge!einfach ein neues Schlüssel / Wert-Paar erstellen kann, da es tatsächlich für einen anderen Zweck verwendet wird.
PericlesTheo

Guter Punkt. Ich denke, es kann auch von anderen Faktoren abhängen, die das OP nicht veröffentlicht hat.
Michael Durrant

1
Ah danke. Sieht so aus, als ob die Speichermethode etwas Ähnliches tut. Dies war hauptsächlich eine akademische Frage, da ich << als eine Möglichkeit zum Anhängen an Arrays gesehen habe, aber sehen wollte, ob es für Hashes funktioniert. Danke noch einmal.
Jcarpio

5
Der Unterschied ist folgender: storeFügt einfach ein neues Paar hinzu, es ist egal, ob der Schlüssel bereits vorhanden ist. mit merge!jedoch Einträge mit Nachschlüssel außer Kraft gesetzt werden , so dass die Methode ein bisschen mehr als nur Paare hinzuzufügen. Wenn Sie die beiden vergleichen, werden Sie feststellen store, dass Sie schneller sind (trivial, jedoch besonders bei kleinen Hashes)
PericlesTheo

2
@jcarpio Danke. Hash#merge!Gibt den Empfänger-Hash genauso zurück wie Array#<<das Empfänger-Array. Hash#storeist eine ganz andere Sache. Mit der Hash-Syntax Zucker key: "bar"in der Argumentationsposition dachte ich auch, dass dies der Punkt ist, den Sie Ihrer Notation am nächsten kommen können. Ich wusste, dass dieser näher an dem ist, was Sie wollten.
Sawa

89

Da Hashes nicht von Natur aus geordnet sind, gibt es keine Vorstellung von Anhängen. Ruby-Hashes seit 1.9 behalten jedoch die Einfügereihenfolge bei. Hier finden Sie Möglichkeiten zum Hinzufügen neuer Schlüssel / Wert-Paare.

Die einfachste Lösung ist

h[:key] = "bar"

Wenn Sie eine Methode wünschen, verwenden Sie store:

h.store(:key, "bar")

Wenn Sie wirklich, wirklich einen "Schaufel" -Operator ( <<) verwenden möchten , wird dieser tatsächlich an den Wert des Hash als Array angehängt, und Sie müssen den Schlüssel angeben:

h[:key] << "bar"

Das Obige funktioniert nur, wenn der Schlüssel vorhanden ist. Um einen neuen Schlüssel anzuhängen, müssen Sie den Hash mit einem Standardwert initialisieren. Dies können Sie folgendermaßen tun:

h = Hash.new {|h, k| h[k] = ''}
h[:key] << "bar"

Sie könnten versucht sein, Hash-Affen zu patchen, um einen Schaufeloperator einzuschließen, der so funktioniert, wie Sie es geschrieben haben:

class Hash
  def <<(k,v)
    self.store(k,v)
  end
end

Dies erbt jedoch nicht den "syntaktischen Zucker", der in anderen Kontexten auf den Schaufeloperator angewendet wird:

h << :key, "bar" #doesn't work
h.<< :key, "bar" #works

Gründlich! Vielen Dank für den Beitrag und den Einblick.
Jcarpio

Ab Ruby 1.9 werden Hashes bestellt.
Stahl

1
Ruby 1.9+ behält die Einfügereihenfolge bei, aber ein Hash als Datenstruktur hat nicht das Konzept einer inhärenten Reihenfolge.
Mark Thomas

26

Nein, ich glaube nicht, dass Sie Schlüssel / Wert-Paare anhängen können. Das einzige, was mir am nächsten kommt , ist die Verwendung der storeMethode:

h = {}
h.store("key", "value")

3

Vielleicht möchten Sie Hash # zusammenführen?

1.9.3p194 :015 > h={}
 => {} 
1.9.3p194 :016 > h.merge(:key => 'bar')
 => {:key=>"bar"} 
1.9.3p194 :017 > 

Wenn Sie das Array an Ort und Stelle ändern möchten, verwenden Sie merge!

1.9.3p194 :016 > h.merge!(:key => 'bar')
 => {:key=>"bar"} 

Ich denke nicht, dass mergees eine gute Idee ist, weil es ein neues Array zurückgibt; Das neue Paar wird nicht zum vorhandenen Hash hinzugefügt.
PericlesTheo

Wie wäre es mit dem merge!(dh zu vorhandenen Array) statt merge?
Michael Durrant

1
merge!Technisch funktioniert dies in diesem Zusammenhang, aber ich denke, es sollte zum Zusammenführen von zwei Hashes verwendet werden, anstatt einfach ein neues Paar hinzuzufügen. Auch wenn Sie Benchmarking ist merge!, ist es langsamer als store;)
PericlesTheo

3

Ähnlich wie sie sind, merge!und storebehandeln bestehende Hashes unterschiedlich auf Keynames abhängig und wird daher Ihre Präferenz beeinflussen. Anders als das aus einer Syntax Sicht merge!‚s key: "value"Syntax entspricht eng gegen JavaScript und Python. Ich persönlich habe es immer gehasst, Schlüssel-Wert-Paare durch Kommas zu trennen.

hash = {}
hash.merge!(key: "value")
hash.merge!(:key => "value")
puts hash

{:key=>"value"}

hash = {}
hash.store(:key, "value")
hash.store("key", "value")
puts hash

{:key=>"value", "key"=>"value"}

Um den Schaufelbediener zum Laufen zu bringen <<, würde ich empfehlen, die Antwort von Mark Thomas zu verwenden .


1

Ich musste etwas Ähnliches tun, aber ich musste Werte mit denselben Schlüsseln hinzufügen. Wenn ich Merge oder Update verwende, kann ich keine Werte mit denselben Tasten übertragen. Also musste ich eine Reihe von Hashes verwenden.

    my_hash_static = {:header =>{:company => 'xx', :usercode => 'xx', :password => 'xx',
                      :type=> 'n:n', :msgheader => from}, :body=>[]}
    my_hash_dynamic = {:mp=>{:msg=>message, :no=>phones} }        
    my_hash_full = my_hash_static[:body].push my_hash_dynamic
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.