Ak mám pole hashov, každý s denným kľúčom:
[
{:day=>4,:name=>"Jay"},
{:day=>1,:name=>"Ben"},
{:day=>4,:name=>"Jill"}
]
Aký je najlepší spôsob prevodu na hash s hodnotami zoradených dní ako kľúčmi:
{
:1=>[{:day=>1,:name=>"Ben"}],
:4=>[{:day=>4,:name=>"Jay"},{:day=>4,:name=>"Jill"}]
}
Používam Ruby 1.9.2 a Rails 3.1.1
odpovede:
4 pre odpoveď č. 1Osobne by som sa neobťažoval „triediť“ kľúče (čo predstavuje čas objednania podľa času v Ruby 1.9), kým to skutočne nebudem potrebovať. Potom môžete použiť 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"}]}
Namiesto toho kľúče triedte, keď ich skutočne potrebujete.
1 pre odpoveď č. 2
Za predpokladu, že sa vaše pole volá, je list
, tu je jeden spôsob použitia reduce
metóda:
list.reduce({}) { |hash, item|
(hash[item[:day]] ||= []) << item; hash
}
Tu je ďalší, ktorý používa map
metódou, ale musíte nosiť nosnú premennú okolo:
hash = {}
list.each { |item|
(hash[item[:day]] ||= []) << item
}
Keď budete mať netriedený hash povedzte v premennej foo
, môžete to triediť ako,
Hash[foo.sort]
0 pre odpoveď č. 3
Jednoduchá odpoveď:
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
Problém s týmto riešením: Hodnota hash nie je zoradená podľa požiadaviek. (Rovnaký problém má Anuragovo riešenie).
Odpoveď teda musíte trochu upraviť:
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 pre odpoveď č. 4
V Rails môžete použiť OrderedHash
:
ActiveSupport::OrderedHash[arr.group_by { |a| a[:day] }.sort_by(&:first)]
aktualizácia: V skutočnosti je v Ruby 1.9 objednaný hash, takže pomocou ActiveSupport
rozšírenie nie je potrebné:
Hash[arr.group_by { |a| a[:day] }.sort_by(&:first)]