620 votes

Comment additionner un tableau de nombres en Ruby ?

J'ai un tableau d'entiers.

Par exemple :

array = [123,321,12389]

Existe-t-il un moyen agréable d'obtenir la somme de ces deux éléments ?

Je sais, que

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

fonctionnerait.

40 votes

Veuillez noter que Ruby 2.4+ dispose de array.sum

1 votes

Ruby 2.6 ne l'a pas. Ruby donne, Ruby reprend, semble-t-il.

2 votes

@Lori hmm ? lien

859voto

jomey Points 4931

Pour ruby >= 2.4 vous pouvez utiliser somme :

array.sum

Pour ruby < 2.4 vous pouvez utiliser injecter :

array.inject(0, :+)

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

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

6 votes

Comment puis-je utiliser cette méthode pour additionner un attribut d'un objet. Dans mon tableau [product1, product2], je veux additionner product1.price + product2.price. Est-ce possible en utilisant array.inject(:+) ?

1 votes

Pablo : Vous pouvez faire : array.map{|p| p.price}.inject(+ :)

7 votes

Vous pouvez utiliser une astuce similaire avec la méthode map : array.map(&:price).inject(:+)

644voto

zenazn Points 8373

Essayez ça :

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

Voir la documentation sur les Enumérables de Ruby

(remarque : le 0 Le cas de base est nécessaire pour que 0 sera retourné sur un tableau vide au lieu de nil )

327 votes

De l'avocat array.inject(:+) est plus efficace.

4 votes

array.inject(:+) semble causer problème dans Ruby 1.8.6, les exceptions " LocalJumpError : no block given " peuvent apparaître.

37 votes

Dans les rails array.sum pourrait vous donner la somme des valeurs du tableau.

305voto

Evan Points 1850
array.reduce(0, :+)

Bien que cela soit équivalent à array.inject(0, :+) le terme réduire le site est en train d'entrer dans un langage plus commun avec l'apparition de Modèles de programmation MapReduce .

injecter , réduire le site , pliage , accumuler y compresser sont tous synonymes d'une classe de fonctions de pliage . Je trouve que la cohérence dans votre base de code est la 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 souligner le verbiage de map-reduce, voici une version qui est un peu plus indulgente sur ce qui se retrouve dans ce tableau.

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

Quelques lectures supplémentaires pertinentes :

12 votes

Je suis d'accord, reduce m'en dit plus sur ce que fait la fonction, mais inject a l'air beaucoup plus cool.

1 votes

D'accord avec le dernier commentaire, vous m'avez donné la meilleure réponse.

1 votes

Le seul commentaire que je ferais est que reduce y map car les fonctions d'ordre supérieur sont antérieures à MapReduce. L'inspiration va dans l'autre sens. Et dans le sens de MapReduce, il s'agit d'une opération quelque peu différente d'une simple réduction fonctionnelle, ayant des implications sur la façon dont les différentes machines communiquent.

118voto

Mike Woodhouse Points 27748

Sinon (juste pour comparer), si vous avez installé Rails (en fait juste ActiveSupport) :

require 'activesupport'
array.sum

13 votes

Les nouvelles versions d'activesupport ne chargent pas toutes les extensions par défaut. Vous voudrez soit exiger seulement le module sum : require 'active_support/core_ext/enumerable.rb' ou exigent tout le soutien actif : require 'active_support/all' . Pour en savoir plus, cliquez ici : Docs API

2 votes

Peu importe que activesupport est un massif dépendance à glisser dans un projet pour aller de array.inject(:+) a array.sum .

1 votes

Un petit bémol à un commentaire par ailleurs intéressant : il faudrait que ce soit require 'active_support/core_ext/enumerable' sans le .rb puisque ce suffixe est ajouté implicitement.

96voto

jrhicks Points 5369

Pour Ruby >=2.4.0, vous pouvez utiliser sum de Enumerables.

[1, 2, 3, 4].sum

Il est dangereux de mokeypatch les classes de base. Si vous aimez le danger et utiliser une ancienne version de Ruby, vous pouvez ajouter #sum au Array classe :

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

1 votes

S'il te plaît, ne fais pas ça.

0 votes

@user3467349 pourquoi ?

19 votes

Monkeypatching des classes de base n'est pas agréable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X