Je comprends que pour sommer les éléments d’un tableau en Ruby, on peut utiliser la méthode inject, c’est-à-dire.
array = [1,2,3,4,5];
puts array.inject(0, &:+)
Mais comment additionner les propriétés des objets dans un tableau d’objets, par exemple?
Il y a un tableau d'objets et chaque objet a une propriété "cash" par exemple. Je veux donc additionner leurs soldes de trésorerie en un seul. Quelque chose comme...
array.cash.inject(0, &:+) # (but this doesn't work)
Je réalise que je pourrais probablement créer un nouveau tableau composé uniquement de l'argent de la propriété et le résumer, mais je recherche une méthode plus propre si possible!
array.map(&:cash).inject(0, &:+)
ou
array.inject(0){|sum,e| sum + e.cash }
#reduce
prend un bloc (le &:+
est un raccourci pour créer un proc/block qui fait +
). C'est une façon de faire ce que vous voulez:
array.reduce(0) { |sum, obj| sum + obj.cash }
Manière la plus concise:
array.map(&:cash).sum
Si le tableau résultant de la carte ne contient aucun élément:
array.map(&:cash).compact.sum
Il n'est pas nécessaire d'utiliser l'injection initiale et l'opération peut être plus courte
array.map(&:cash).inject(:+)
Voici quelques repères intéressants
array = Array.new(1000) { OpenStruct.new(property: Rand(1000)) }
Benchmark.ips do |x|
x.report('map.sum') { array.map(&:property).sum }
x.report('inject(0)') { array.inject(0) { |sum, x| sum + x.property } }
x.compare!
end
Et résultats
Calculating -------------------------------------
map.sum 249.000 i/100ms
inject(0) 268.000 i/100ms
-------------------------------------------------
map.sum 2.947k (± 5.1%) i/s - 14.691k
inject(0) 3.089k (± 5.4%) i/s - 15.544k
Comparison:
inject(0): 3088.9 i/s
map.sum: 2947.5 i/s - 1.05x slower
Comme vous pouvez le voir, injecter un peu plus vite
Si la valeur de départ pour la somme est 0, la somme seule est identique à injecter:
array.map(&:cash).sum
Et je préférerais la version en bloc:
array.sum { |a| a.cash }
Parce que le symbole Proc from est souvent trop limité (pas de paramètres, etc.).
(Nécessite Active_Support)