2011-07-04 3 views
1

Y a-t-il une meilleure façon de faire ce qui suit?ruby ​​(w/rails) group_by, puis group_by again

prices = Price...all.group_by(&:foreign_key_id) 
@prices = Hash.new 
prices.each {|k, v| @prices[k] = Hash.new if [email protected][k]; @prices[k] = v.group_by {|g| g.created_at.to_time.to_i } } 

Je voudrais faire quelque chose comme

prices.each {|k,v| v = v.group_by(&:created_at) } 

Mais cela ne semble pas fonctionner parce que v est un tableau et group_by produit un hachage. Peut-être y at-il un moyen de le faire avec injecter?

Répondre

1
prices.inject(Hash.new{ |h, k| h[k] = {} }) { |h, (k, v)| 
    h[k] = v.group_by(&:created_at) 
    h 
} 

Ajouté: façon fonction Moins:

prices.keys.each { |k| 
    prices[k] = prices[k].group_by(&:created_at) 
} 
+0

prices.each_key.to_a ~> prices.keys – andrykonchin

+0

Il est toujours bon de voir un bon usage d'injecter, et même si cela a du sens après l'avoir regardé, je n'aurais jamais su faire ça, merci! – Scott

+0

@aaz Merci, j'ai commencé par '.each_key {| k | ... 'et finalement créé quelque chose d'extrêmement complexe. Corrigée. –

0

peut être

prices.each {|k,v| prices[k] = v.group_by(&:created_at) } 

ou

new_prices = {} 
prices.each {|k,v| new_prices[k] = v.group_by(&:created_at) } 

Hash ne supporte pas injecter

+1

Bien sûr hash soutenir 'inject':' {} .methods.grep/inj/# => [: injecter] '. 'h = {a: 1, b: 2}; h.inject (0) {| s, (k, v) | s + v} # => 3'. –

+0

thx, je ne sais pas – andrykonchin

+0

Il supporte injecter comme n'importe quelle classe qui implémente 'each' et' include Enumerable' –

0

Cela devrait fonctionner:

prices = Price...all.inject({}) do |hash, el| 
    (hash[el.foreign_key_id] ||={})[el.created_at] << el 
    hash 
end 

mais je ubt que vous aurez deux enregistrements avec la même valeur created_at.

Vous devrez peut-être définir le format pour created_at.

Quelque chose comme ceci:

prices = Price...all.inject({}) do |hash, el| 
    (hash[el.foreign_key_id] ||={})[el.created_at.to_s(:db)] << el 
    hash 
end 
0

Je comprends la deuxième group_by, mais le premier, je pense que ce sera une logique de modèle, donc, dépend de votre type de relation que vous pouvez utiliser dans votre modèle les options : :uniq => true ou :group => 'foreign_key_id'. Vous pouvez le lire ici http://guides.rubyonrails.org/association_basics.html

+0

Voulez-vous dire utiliser: group sur la clause 'has_many'? Je n'ai pas essayé cela, mais je devrais ajouter une autre ligne has_many, en l'appelant quelque chose d'autre. Je n'utilise pas toujours les prix groupés. – Scott