/ / Come posso convertire un array di hash in un hash ordinato? - ruby-on-rails, ruby, array, hash

Come posso convertire un array di hash in un hash ordinato? - ruby-on-rails, ruby, array, hash

Se ho un array di hash, ognuno con una chiave del giorno:

[
{:day=>4,:name=>"Jay"},
{:day=>1,:name=>"Ben"},
{:day=>4,:name=>"Jill"}
]

Qual è il modo migliore per convertirlo in un hash con valori di giorni ordinati come chiavi:

{
:1=>[{:day=>1,:name=>"Ben"}],
:4=>[{:day=>4,:name=>"Jay"},{:day=>4,:name=>"Jill"}]
}

Sto usando Ruby 1.9.2 e Rails 3.1.1

risposte:

4 per risposta № 1

Personalmente, non mi preoccuperei di "ordinare" i tasti (che equivale a ordinare per voce in Ruby 1.9) finché non ne avessi avuto bisogno. group_by:

arr = [{:day=>4,:name=>"Jay"}, {:day=>1,:name=>"Ben"}, {:day=>4,:name=>"Jill"}]
arr.group_by { |a| a[:day] }
=> {4=>[{:day=>4, :name=>"Jay"}, {:day=>4, :name=>"Jill"}],
1=>[{:day=>1, :name=>"Ben"}]}

Invece, ordina i tasti quando ne hai effettivamente bisogno.


1 per risposta № 2

Supponendo che la matrice sia chiamata è list, ecco un modo usando il reduce metodo:

list.reduce({}) { |hash, item|
(hash[item[:day]] ||= []) << item; hash
}

Ecco un altro usando il map metodo, ma devi portare una variabile titolare intorno:

hash = {}
list.each { |item|
(hash[item[:day]] ||= []) << item
}

Una volta che hai l'hash indifferenziato nella variabile foo, puoi ordinarlo come,

Hash[foo.sort]

0 per risposta № 3

Risposta semplice:

data = [
{:day=>4,:name=>"Jay"},
{:day=>1,:name=>"Ben"},
{:day=>4,:name=>"Jill"}
]

#expected solution
sol = {
1=>[{:day=>1,:name=>"Ben"}],
4=>[{:day=>4,:name=>"Jay"},{:day=>4,:name=>"Jill"}]
}

res = {}
data.each{|h|
res[h[:day]] ||=  []
res[h[:day]] << h
}

p res
p res == sol    #check value
p res.keys == sol.keys  #check order

Problema con questa soluzione: l'hash non è ordinato come richiesto. (Lo stesso problema ha Soluzione Anurags).

Quindi è necessario modificare la risposta un po ':

res = {}
data.sort_by{|h| h[:day]}.each{|h|
res[h[:day]] ||=  []
res[h[:day]] << h
}

p res
p res == sol    #check value
p res.keys == sol.keys  #check order

0 per risposta № 4

In Rails puoi usare OrderedHash:

ActiveSupport::OrderedHash[arr.group_by { |a| a[:day] }.sort_by(&:first)]

Aggiornare: Infatti in Ruby 1.9 l'hash è ordinato, quindi usando ActiveSupport l'estensione non è richiesta:

Hash[arr.group_by { |a| a[:day] }.sort_by(&:first)]