Array naar Hash Ruby

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_hmethode 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%

Enumeratorbevat Enumerable. Sinds 2.1heeft Enumerableook 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_slicezonder blok geeft ons Enumerator, en volgens de bovenstaande uitleg kunnen we de #to_hmethode aanroepen op het Enumeratorobject.


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 2paar 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 Arrayvoor 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 assocen reduceom hierboven in één regel te doen, maar dat wordt veel moeilijker om te redeneren en lezen.

Other episodes