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 № 1Personalmente, 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)]