Question Comment faire une somme de nombres dans Ruby?


J'ai un tableau d'entiers.

Par exemple:

array = [123,321,12389]

Y a-t-il une belle façon d'en obtenir la somme?

Je le sais

sum = 0
array.each { |a| sum+=a }

travaillerait.


511
2017-10-08 16:04


origine


Réponses:


Essaye ça:

array.inject(0){|sum,x| sum + x }

Voir la documentation énumérable de Ruby

(noter la 0 cas de base est nécessaire pour que 0 sera retourné sur un tableau vide au lieu de nil)


567
2017-10-08 16:07



Ou essayez la méthode Ruby 1.9:

array.inject(0, :+)

Noter la 0 cas de base est nécessaire sinon nil sera retourné sur les tableaux vides:

> [].inject(:+)
nil
> [].inject(0, :+)
0

768
2017-10-08 16:28



array.reduce(0, :+)

Bien qu'équivalent à array.inject(0, :+), le terme réduire entre dans une langue vernaculaire plus commune avec la montée de Modèles de programmation MapReduce.

injecter, réduire, plier, accumuler, et compresse sont tous synonymes de classe fonctions de pliage. Je trouve la cohérence dans votre base de code plus importante, mais comme diverses communautés ont tendance à préférer un mot plutôt qu'un autre, il est néanmoins utile de connaître les alternatives.

Pour mettre en évidence le verbiage map-reduce, voici une version qui pardonne un peu plus sur ce qui finit dans ce tableau.

array.map(&:to_i).reduce(0, :+)

Quelques lectures pertinentes supplémentaires:


271
2017-12-14 17:06



Alternativement (juste pour comparaison), si vous avez installé Rails (en fait seulement ActiveSupport):

require 'activesupport'
array.sum

106
2017-10-08 16:49



Il est dangereux de mokeypatch classes de base et maintenant que Ruby 2.4.0 a somme sur Enumerables il n'est pas nécessaire et dangereux. Si vous aimez le danger et en utilisant une ancienne version de Ruby, vous pouvez ajouter #sum au Array classe:

class Array
  def sum
    inject(0) { |sum, x| sum + x }
  end
end

Ensuite, faites des choses amusantes comme:

[1, 2, 3, 4].sum

50
2017-10-08 18:29



Nouveau pour Ruby 2.4.0

Vous pouvez utiliser la méthode bien nommée Enumerable#sum. Il a beaucoup d'avantages par rapport à inject(:+) mais il y a aussi des notes importantes à lire à la fin.

Exemples

Gammes

(1..100).sum
#=> 5050

Tableaux

[1, 2, 4, 9, 2, 3].sum
#=> 21

[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7

Note importante

Cette méthode n'est pas équivalente à #inject(:+). Par exemple

%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer

Aussi,

(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)

Voir cette réponse pour plus d'informations sur pourquoi sum est comme ça.


26
2018-01-04 03:33



Pour des raisons de diversité, vous pouvez également le faire si votre tableau n'est pas un tableau de nombres, mais plutôt un tableau d'objets qui ont des propriétés qui sont des nombres (par exemple, nombre):

array.inject(0){|sum,x| sum + x.amount}

19
2017-07-24 14:23



ruby 1.8.7 est la suivante:

array.inject(0, &:+) 

18
2018-06-22 15:56