J'ai un tableau d'entiers.
Par exemple:
array = [123,321,12389]
Existe-t-il un bon moyen d’en obtenir la somme?
Je le sais
sum = 0
array.each { |a| sum+=a }
travaillerait.
Essaye ça:
array.inject(0){|sum,x| sum + x }
Voir la documentation énumérable de Ruby
(Remarque: le cas de base 0
est nécessaire pour que 0
soit renvoyé dans un tableau vide au lieu de nil
.)
Ou essayez la méthode Ruby 1.9:
array.inject(0, :+)
Remarque: le cas de base 0
est nécessaire, sinon nil
sera renvoyé sur des tableaux vides:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.reduce(0, :+)
Bien que équivalent à array.inject(0, :+)
, le terme réduire entre dans une langue plus courante avec la montée de modèles de programmation MapReduce .
injecter , réduire , fois , accumule et compresse sont tous synonymes en tant que classe de fonctions de pliage . Je pense que la cohérence entre les codes de votre base est essentielle, mais comme différentes 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 réduction de carte, voici une version un peu plus indulgente de ce qui se trouve dans ce tableau.
array.map(&:to_i).reduce(0, :+)
Quelques lectures pertinentes supplémentaires:
Alternativement (juste à titre de comparaison), si vous avez Rails installé (en fait seulement ActiveSupport):
require 'activesupport'
array.sum
Pour Ruby> = 2.4.0, vous pouvez utiliser sum
de Enumerables.
[1, 2, 3, 4].sum
Il est dangereux de mokeypatch classes de base. Si vous aimez danger et que vous utilisez une version plus ancienne de Ruby, vous pouvez ajouter #sum
à la classe Array
:
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 par rapport à inject(:+)
, mais vous devez également lire quelques notes importantes à 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 comme ceci.
Ruby 2.4+/Rails - array.sum
c'est-à-dire [1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
ou array.reduce(:+)
* Remarque: La méthode #sum
est un nouvel ajout à la version 2.4 de enumerable
. Vous pourrez donc utiliser array.sum
en pur Ruby, et pas uniquement dans Rails.
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 dont les propriétés sont des nombres (par exemple, un montant):
array.inject(0){|sum,x| sum + x.amount}
Ruby 1.8.7 façon est la suivante:
array.inject(0, &:+)
Vous pouvez simplement utiliser:
example = [1,2,3]
example.inject(:+)
C'est assez [1,2,3].inject('+')
Ruby 2.4.0 est publié et utilise une méthode Enumerable # sum . Donc tu peux 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 de [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 un compact puis injecter la somme
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
array.reduce(:+)
Fonctionne pour gammes aussi ... par conséquent,
(1..10).reduce(:+) returns 55
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 des valeurs nil et vide, par défaut si vous utilisez l'une des fonctions ci-dessus, réduisez, sommez, injectez tout dans le
TypeError: nil ne peut pas être forcé dans Integer
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 la ou les expressions Ruby dans la 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+
Si vous vous sentez golfy, vous pouvez faire
eval([123,321,12389]*?+)
Cela créera une chaîne "123 + 321 + 12389", puis utilisera la fonction eval pour effectuer la somme. Ceci est niquement à des fins de golf, vous ne devriez pas l'utiliser dans le code approprié.
Ou vous pouvez essayer cette méthode:
def sum arr
0 if arr.empty
arr.inject :+
end
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 le champ [].
C'est le chemin le plus court. L'essayer.
array.inject :+