Okay, hier ist der Deal, ich habe lange gegoogelt, um eine Lösung dafür zu finden, und obwohl es viele gibt, scheinen sie nicht den Job zu machen, den ich suche.
Grundsätzlich habe ich ein Array wie folgt aufgebaut
["item 1", "item 2", "item 3", "item 4"]
Ich möchte dies in einen Hash konvertieren, damit es so aussieht
{ "item 1" => "item 2", "item 3" => "item 4" }
Das heißt, die Elemente in den "geraden" Indizes sind die Schlüssel und die Elemente in den "ungeraden" Indizes sind die Werte.
Irgendwelche Ideen, wie man das sauber macht? Ich nehme an, eine Brute-Force-Methode wäre, einfach alle geraden Indizes in ein separates Array zu ziehen und sie dann zu durchlaufen, um die Werte hinzuzufügen.
*
heißt der Splat- Operator. Es nimmt ein Array und konvertiert es in eine Literalliste von Elementen. Also*[1,2,3,4]
=>1, 2, 3, 4
. In diesem Beispiel entspricht das oben Gesagte dem AusführenHash["item 1", "item 2", "item 3", "item 4"]
. UndHash
hat eine[]
Methode, die eine Liste von Argumenten akzeptiert (wobei gerade Indexschlüssel und ungerade Indexwerte erstellt werden), aberHash[]
kein Array akzeptiert, also teilen wir das Array mit*
.Hash[a.each_slice(2).to_a]
.Ruby 2.1.0 hat eine
to_h
Methode für das Array eingeführt, die genau das tut, was Sie benötigen, wenn Ihr ursprüngliches Array aus Arrays von Schlüssel-Wert-Paaren besteht: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h .quelle
bar
muss ein Symbol sein, und das Symbol:2
sollte eine Ganzzahl sein. Ihr korrigierter Ausdruck ist alsoa = [[:foo, 1], [:bar, 2]]
).Verwenden Sie einfach
Hash.[]
mit den Werten im Array. Beispielsweise:quelle
*arr
Konvertiertarr
in eine Argumentliste, daher wird die[]
Hash-Methode mit dem Inhalt von arr als Argument aufgerufen .Oder wenn Sie ein Array von
[key, value]
Arrays haben, können Sie Folgendes tun:quelle
Hash[*arr]
{ [1, 2] => [3, 4] }
. Und da der Titel der Frage "Array to Hash" lautet und die integrierte "Hash to Array" -Methode Folgendes tut:{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]
Ich dachte, mehr als einer könnte hier enden und versuchen, die Umkehrung der integrierten "Hash to Array" -Methode zu erreichen. Eigentlich bin ich hier sowieso so gelandet.Hash[arr]
wird den Job für Sie erledigen.#inject
Methoden. Mit#merge!
,#each_with_object
sollte verwendet worden sein. Wenn#inject
darauf bestanden wird,#merge
anstatt#merge!
hätte verwendet werden sollen.Das habe ich gesucht, als ich das gegoogelt habe:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
quelle
merge
, es erstellt und verwirft einen neuen Hash pro Schleifeniteration und ist sehr langsam. Wenn Sie[{a:1},{b:2}].reduce({}, :merge!)
stattdessen eine Reihe von Hashes haben, wird alles in demselben (neuen) Hash zusammengeführt..reduce(&:merge!)
[{a: 1}, {b: 2}].reduce(&:merge!)
bewertet zu{:a=>1, :b=>2}
[{a: 1}, {b: 2}].reduce(&:merge!)
ist das gleiche wie[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }
das gleiche wie[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
.Enumerator
beinhaltetEnumerable
. Da2.1
hatEnumerable
auch eine Methode#to_h
. Deshalb können wir schreiben:Weil
#each_slice
wir ohne BlockEnumerator
und gemäß der obigen Erklärung die#to_h
Methode für dasEnumerator
Objekt aufrufen können .quelle
Sie können dies für ein einzelnes Array versuchen
für Array von Array
quelle
oder, wenn Sie hassen
Hash[ ... ]
:oder, wenn Sie ein fauler Fan von defekter funktionaler Programmierung sind:
quelle
Hash[ ... ]
aber es als verkettete Methode verwenden möchten (wie Sie es tun könnento_h
), können Sie Boris Vorschläge kombinieren und schreiben:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
Alle Antworten setzen voraus, dass das Startarray eindeutig ist. OP hat nicht angegeben, wie Arrays mit doppelten Einträgen behandelt werden sollen, die zu doppelten Schlüsseln führen.
Schauen wir uns an:
Sie werden die verlieren
item 1 => item 2
Paar , wie es überschriebene bij istitem 1 => item 5
:Alle Methoden, einschließlich des
reduce(&:merge!)
Ergebnisses, führen zum gleichen Entfernen.Es könnte jedoch sein, dass dies genau das ist, was Sie erwarten. In anderen Fällen möchten Sie wahrscheinlich
Array
stattdessen ein Ergebnis mit einem for-Wert erhalten:Der naive Weg wäre, eine Hilfsvariable zu erstellen, einen Hash mit einem Standardwert, und diesen dann in eine Schleife zu füllen:
Es mag möglich sein, oben in einer Zeile zu verwenden
assoc
undreduce
zu tun, aber es wird viel schwieriger, darüber nachzudenken und zu lesen.quelle