J'ai un tableau d'entiers.
Par exemple:
array = [123,321,12389]
Y a-t-il un bon moyen d'en obtenir la somme?
Je le sais
sum = 0
array.each { |a| sum+=a }
travaillerait.
J'ai un tableau d'entiers.
Par exemple:
array = [123,321,12389]
Y a-t-il un bon moyen d'en obtenir la somme?
Je le sais
sum = 0
array.each { |a| sum+=a }
travaillerait.
Réponses:
Essaye ça:
array.inject(0){|sum,x| sum + x }
Voir la documentation énumérable de Ruby
(note: le 0
cas de base est nécessaire pour qu'il 0
soit retourné sur un tableau vide au lieu de nil
)
array.inject(:+)
est plus efficace.
array.inject(:+)
semble causer des problèmes dans Ruby 1.8.6 Exceptions "LocalJumpError: aucun bloc donné" pourrait apparaître.
array.sum
peut vous donner la somme des valeurs du tableau.
reduce
, qui est un alias de inject
(comme dans array.reduce( :+ )
).
inject
plutôt que reduce
.
Ou essayez la méthode Ruby 1.9:
array.inject(0, :+)
Remarque: le 0
cas de base est nécessaire sinon nil
il sera retourné sur des tableaux vides:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
est un peu plus sûr. Il s'assure que si vous avez une liste vide, vous obtenez 0 au lieu de zéro .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Bien qu'équivalent à array.inject(0, :+)
, le terme réduire entre dans une langue vernaculaire plus courante avec l'essor des modèles de programmation MapReduce .
injecter , réduire , plier , accumuler et compresser sont tous synonymes d'une classe de fonctions de pliage . Je trouve la cohérence dans votre base de code la plus importante, mais comme diverses communautés ont tendance à préférer un mot à un autre, il est néanmoins utile de connaître les alternatives.
Pour souligner le verbiage de réduction de carte, 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 pertinentes supplémentaires:
reduce
me dit plus sur ce que fait la fonction, mais inject
sonne beaucoup plus cool.
reduce
et map
comme les fonctions d'ordre supérieur sont antérieures à MapReduce. L'inspiration va dans l'autre sens. Et dans le sens 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.
Alternativement (juste pour comparaison), si vous avez installé Rails (en fait juste ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
, ou besoin tout soutien actif: require 'active_support/all'
. Pour en savoir plus, cliquez ici: API Docs
activesupport
une dépendance massive à glisser dans un projet pour aller de array.inject(:+)
à array.sum
.
require 'active_support/core_ext/enumerable'
sans le .rb
suffixe, car il est ajouté implicitement.
Pour Ruby> = 2.4.0, vous pouvez utiliser sum
depuis Enumerables.
[1, 2, 3, 4].sum
Il est dangereux de mokeypatch les classes de base. Si vous aimez le danger et utilisez une ancienne version de Ruby, vous pouvez ajouter #sum
à la Array
classe:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Vous pouvez utiliser la méthode bien nommée Enumerable#sum
. Il présente de nombreux avantages, inject(:+)
mais il y a également des notes importantes à lire à la fin.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
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-ce comme ça.
Ruby 2.4+ / Rails - array.sum
ie[1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
ouarray.reduce(:+)
* Remarque: La #sum
méthode est un nouvel ajout à la version 2.4 pour enumerable
que vous puissiez désormais l'utiliser array.sum
en rubis pur, pas seulement Rails.
Dans un souci 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 quantité):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Voir d'autres réponses.
map
alors inject
vous devez faire une boucle à travers le réseau deux fois: une fois pour créer un nouveau tableau, l'autre pour sommer les membres. Cette méthode est légèrement plus verbeuse, mais aussi plus efficace.
ruby 1.8.7 way est le suivant:
array.inject(0, &:+)
Vous pouvez simplement utiliser:
example = [1,2,3]
example.inject(:+)
inject(:+)
mais cela ne fonctionne pas inject :+
?
C'est assez
[1,2,3].inject('+')
Ruby 2.4.0 est sorti, et il a une méthode de somme Enumerable # . Vous pouvez donc faire
array.sum
Exemples tirés de la documentation:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
Permet également [1,2].sum{|x| x * 2 } == 6
:
# http://madeofcode.com/posts/74-ruby-core-extension-array-sum
class Array
def sum(method = nil, &block)
if block_given?
raise ArgumentError, "You cannot pass a block and a method!" if method
inject(0) { |sum, i| sum + yield(i) }
elsif method
inject(0) { |sum, i| sum + i.send(method) }
else
inject(0) { |sum, i| sum + i }
end
end
end
pour un tableau avec des valeurs nulles, nous pouvons faire compact, puis injecter la somme ex-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
Méthode 1:
[1] pry(main)> [1,2,3,4].sum
=> 10
[2] pry(main)> [].sum
=> 0
[3] pry(main)> [1,2,3,5,nil].sum
TypeError: nil can't be coerced into Integer
Méthode 2:
[24] pry(main)> [].inject(:+)
=> nil
[25] pry(main)> [].inject(0, :+)
=> 0
[4] pry(main)> [1,2,3,4,5].inject(0, :+)
=> 15
[5] pry(main)> [1,2,3,4,nil].inject(0, :+)
TypeError: nil can't be coerced into Integer
from (pry):5:in `+'
Méthode 3:
[6] pry(main)> [1,2,3].reduce(:+)
=> 6
[9] pry(main)> [].reduce(:+)
=> nil
[7] pry(main)> [1,2,nil].reduce(:+)
TypeError: nil can't be coerced into Integer
from (pry):7:in `+'
Méthode 4: lorsque Array contient un nil et des valeurs vides, par défaut si vous utilisez l'une des fonctions ci-dessus, réduisez, additionnez, injectez tout sera par le
TypeError: aucun ne peut être contraint en entier
Vous pouvez surmonter cela en,
[16] pry(main)> sum = 0
=> 0
[17] pry(main)> [1,2,3,4,nil, ''].each{|a| sum+= a.to_i }
=> [1, 2, 3, 4, nil, ""]
[18] pry(main)> sum
=> 10
Méthode 6: eval
Évalue les expressions Ruby dans une chaîne.
[26] pry(main)> a = [1,3,4,5]
=> [1, 3, 4, 5]
[27] pry(main)> eval a.join '+'
=> 13
[30] pry(main)> a = [1,3,4,5, nil]
=> [1, 3, 4, 5, nil]
[31] pry(main)> eval a.join '+'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
1+3+4+5+
C'est le chemin le plus court. Essayez-le.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Cela a bien fonctionné pour moi en tant que nouveau développeur. Vous pouvez ajuster votre plage de numéros en modifiant les valeurs dans []
Vous pouvez également le faire de manière simple
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Vous pouvez utiliser .map et .sum comme:
array.map { |e| e }.sum
array.sum
array.sum