Deze array converteren:
a = ["item 1", "item 2", "item 3", "item 4"]
…naar een hash:
{ "item 1" => "item 2", "item 3" => "item 4" }
d.w.z. elementen op evenindexen zijn sleutelsen onevenzijn waarden.
Antwoord 1, autoriteit 100%
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }
Dat is het. De *
wordt de splat-operator genoemd.
Eén waarschuwing per @Mike Lewis (in de opmerkingen): “Wees hier heel voorzichtig mee. Ruby breidt splats op de stapel uit. Als je dit doet met een grote dataset, verwacht je dat je stapel eruit zal blazen.”
Dus voor de meeste algemene gebruiksgevallen is deze methode geweldig, maar gebruik een andere methode als je de conversie op veel gegevens wilt uitvoeren. @Łukasz Niemier (ook in de opmerkingen) biedt bijvoorbeeld deze methode voor grote datasets:
h = Hash[a.each_slice(2).to_a]
Antwoord 2, autoriteit 33%
Ruby 2.1.0 introduceerde een to_h
methode op Array die doet wat je nodig hebt als je originele array uit arrays van sleutel-waardeparen bestaat: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h.
[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}
Antwoord 3, autoriteit 8%
Gebruik gewoon Hash.[]
met de waarden in de array. Bijvoorbeeld:
arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}
Antwoord 4, autoriteit 7%
Of als je een array van [key, value]
arrays hebt, kun je het volgende doen:
[[1, 2], [3, 4]].inject({}) do |r, s|
r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }
Antwoord 5, autoriteit 4%
Dit is wat ik zocht toen ik dit googelde:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v }
=> {:a=>1, :b=>2}
Antwoord 6, autoriteit 3%
Enumerator
bevat Enumerable
. Sinds 2.1
heeft Enumerable
ook een methode #to_h
. Daarom kunnen we schrijven:-
a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}
Omdat #each_slice
zonder blok geeft ons Enumerator
, en volgens de bovenstaande uitleg kunnen we de #to_h
methode aanroepen op het Enumerator
object.
Antwoord 7, autoriteit 2%
Je zou het zo kunnen proberen, voor een enkele array
irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
=> ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
=> {"item 1"=>"item 2", "item 3"=>"item 4"}
voor array of array
irb(main):022:0> a = [[1, 2], [3, 4]]
=> [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
=> {1=>2, 3=>4}
Antwoord 8, autoriteit 2%
a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]
of, als je Hash[ ... ]
haat:
a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end
of, als je een luie fan bent van kapotte functionele programmering:
h = a.lazy.each_slice( 2 ).tap { |a|
break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"
Antwoord 9
Alle antwoorden gaan ervan uit dat de startarray uniek is. OP heeft niet gespecificeerd hoe arrays met dubbele vermeldingen moeten worden behandeld, wat resulteert in dubbele sleutels.
Laten we eens kijken naar:
a = ["item 1", "item 2", "item 3", "item 4", "item 1", "item 5"]
Je verliest het item 1 => item 2
paar zoals het wordt overschreven door item 1 => item 5
:
Hash[*a]
=> {"item 1"=>"item 5", "item 3"=>"item 4"}
Alle methoden, inclusief de reduce(&:merge!)
resulteren in dezelfde verwijdering.
Het kan zijn dat dit precies is wat u verwacht, hoewel. Maar in andere gevallen wilt u waarschijnlijk een resultaat krijgen met een Array
voor waarde in plaats daarvan:
{"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}
De naïeve manier zou zijn om een helpervariabele te creëren, een hash die een standaardwaarde heeft en deze vervolgens in een lus vult:
result = Hash.new {|hash, k| hash[k] = [] } # Hash.new with block defines unique defaults.
a.each_slice(2) {|k,v| result[k] << v }
a
=> {"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}
Het kan mogelijk zijn om assoc
en reduce
om hierboven in één regel te doen, maar dat wordt veel moeilijker om te redeneren en lezen.