J'ai des problèmes avec la syntaxe de réduction. J'ai un hachage du format suivant:
H = {"Key1" => 1, "Key2" => 2}
Je voudrais utiliser réduire pour trouver la somme des valeurs de cette fonction.
Quelque chose comme
H.reduce(0) {|memo, elem| memo+=elem}
Je sais que c'est faux. Je ne comprends pas comment je peux faire de la valeur du hash une valeur elem.
Utilisation Enumerable#reduce
, si vous êtes d'accord pour obtenir nil
si le hachage est vide:
H.values.reduce(:+) # => 3
Hash.new.values.reduce(:+) # => nil
Pour obtenir en toute sécurité 0
lorsque le hachage est vide, utilisez:
H.values.reduce(0) { |sum,x| sum + x } # or...
H.reduce(0) { |sum,(key,val)| sum + val } # ...if you need to inspect the key
Voici une référence rapide, pour les coups de pied. Notez qu'il semble être légèrement plus rapide pour réduire uniquement les valeurs plutôt que les valeurs des paires clé/valeur:
user system total real
H.values.reduce(:+) 4.510000 0.080000 4.590000 ( 4.595229)
H.values.reduce(0) {...} 4.660000 0.080000 4.740000 ( 4.739708)
H.reduce(0) {...} 5.160000 0.070000 5.230000 ( 5.241916)
require 'benchmark'
size = 1_000
hash = Hash[* Array.new(size*2) { Rand } ]
N=10_000
Benchmark.bm(24) do |x|
x.report('H.values.reduce(:+)') { N.times { hash.dup.values.reduce(:+) } }
x.report('H.values.reduce(0) {...}') { N.times { hash.dup.values.reduce(0) { |sum,x| sum + x } } }
x.report('H.reduce(0) {...}') { N.times { hash.dup.reduce(0) { |sum,(_,v)| sum + v } } }
end
Vous pouvez faire en sorte que elem
contienne la valeur en la divisant en 2 variables:
H.reduce(0) {|memo, (key, val)| memo += val}
Essaye ça:
H.reduce(0) { |memo, elem| memo += elem[1] }
ou
H.reduce(0) { |memo, (key, value)| memo += value }
Je sais que je fouille celui-ci, mais si vous utilisez Rails, le .sum
méthode peut aider:
H = {"Key1" => 1, "Key2" => 2}
=> {"Key1"=>1, "Key2"=>2}
> H.values.sum
=> 3
L'avantage est qu'il renvoie 0
sur des hachages vides:
> {}.values.sum
=> 0
> {}.values.reduce(:+)
=> nil
J'ai remarqué qu'il n'était spécifique à Rails qu'après avoir tapé cette réponse. Je sais que l'OP n'a pas ajouté la balise Rails, mais je me suis dit que cela pourrait être utile pour les gens qui passent.
Notez que depuis Ruby 2.4.0, .sum
est maintenant disponible .
h = {"Key1" => 1, "Key2" => 2}
h.values.inject(0){|f,v| f += v.to_i }
# => 3
ou
h.values.inject(:+)
# => 3