web-dev-qa-db-fra.com

Comment faire la somme d'un tableau de nombres en Ruby?

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.

549
brainfck

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.)

597
zenazn

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
794
jomey
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:

278
Evan

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

require 'activesupport'
array.sum
110
Mike Woodhouse

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
58
jrhicks

Nouveau pour Ruby 2.4.0

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.

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 ceci.

40
Eli Sadoff

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.

19
collect

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}
19
HashFail

Ruby 1.8.7 façon est la suivante:

array.inject(0, &:+) 
18
Vova

Vous pouvez simplement utiliser:

    example = [1,2,3]
    example.inject(:+)
16
Ganesh Sagare

C'est assez [1,2,3].inject('+')

5
Mahesh Bablu

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
4
Santhosh

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
3
grosser

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(:+)
3
pawan
array.reduce(:+)

Fonctionne pour gammes aussi ... par conséquent,

(1..10).reduce(:+) returns 55
2
MulleOne

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+
1
Nataraja B

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é.

1
Ulysse BN

Ou vous pouvez essayer cette méthode:

def sum arr
  0 if arr.empty
  arr.inject :+
end
0
ramin
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 [].

0
Madeline Young

C'est le chemin le plus court. L'essayer.

array.inject :+

0
Tej Poudel