web-dev-qa-db-fra.com

Réduire les valeurs de hachage

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.

30
richsoni

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
32
maerics

Vous pouvez faire en sorte que elem contienne la valeur en la divisant en 2 variables:

H.reduce(0) {|memo, (key, val)| memo += val}
70
steenslag

Essaye ça:

H.reduce(0) { |memo, elem| memo += elem[1] }

ou

H.reduce(0) { |memo, (key, value)| memo += value }
5
yasu

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 .

2
astorije
h = {"Key1" => 1, "Key2" => 2}

h.values.inject(0){|f,v| f += v.to_i }
# => 3

ou

h.values.inject(:+)
# => 3
1
user904990