Hoe een reeks getallen in Ruby optellen?

Ik heb een array van gehele getallen.

Bijvoorbeeld:

array = [123,321,12389]

Is er een leuke manier om de som ervan te krijgen?

Ik weet het, dat

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

zou werken.


Antwoord 1, autoriteit 100%

Probeer dit:

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

Zie Ruby’s opsombare documentatie

(opmerking: het basisgeval 0is nodig zodat 0wordt geretourneerd op een lege array in plaats van nil)


Antwoord 2, autoriteit 99%

Of probeer de Ruby 1.9-manier:

array.inject(0, :+)

Opmerking: het basisgeval 0is nodig, anders wordt nilgeretourneerd op lege arrays:

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

Antwoord 3, autoriteit 48%

array.reduce(0, :+)

Hoewel equivalent aan array.inject(0, :+), begint de term reduceeen meer gebruikelijke volkstaal te worden met de opkomst van MapReduce-programmeermodellen.

Inject , verminderen , vouw , accumuleren , en comprimeren zijn allemaal synoniem als een klasse van vouwfuncties . Ik vind consistentie in uw codebasis het belangrijkste, maar aangezien verschillende gemeenschappen de voorkeur geven aan één woord over een ander, is het niettemin nuttig om de alternatieven te kennen.

Om de verbeage van de kaart te benadrukken, is hier een versie die een beetje meer vergevingsgezind is voor wat er in die array terechtkomt.

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

Enkele extra relevante informatie:


Antwoord 4, Autoriteit 18%

Als alternatief (alleen voor vergelijking), als u rails hebt geïnstalleerd (eigenlijk gewoon ActiveSupport):

require 'activesupport'
array.sum

Antwoord 5, Autoriteit 14%

Voor Ruby & GT; = 2.4.0 U kunt sumgebruiken vanuit de incommunautabelen.

[1, 2, 3, 4].sum

Het is gevaarlijk voor MokePatch-basisklassen. Als u van gevaar houdt en een oudere versie van Ruby gebruikt, kunt u #sumtoevoegen aan de Arrayklasse:

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

Antwoord 6, autoriteit 8%

Nieuw voor Ruby 2.4.0

Je kunt de toepasselijk genaamde methode Enumerable#sumgebruiken. Het heeft veel voordelen ten opzichte van inject(:+), maar er zijn ook enkele belangrijke opmerkingen aan het einde.

Voorbeelden

Bereiken

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

Arrays

[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7

Belangrijke opmerking

Deze methode is niet gelijk aan #inject(:+). Bijvoorbeeld

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

Ook

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

Zie dit antwoordvoor meer informatie over waarom sumzo is.


Antwoord 7, autoriteit 3%

Ruby 2.4+ / Rails – array.sumd.w.z. [1, 2, 3].sum # => 6

Ruby pre 2.4 – array.inject(:+)of array.reduce(:+)

*Opmerking: de methode #sumis een nieuwe toevoeging aan 2.4 voor enumerable, dus u kunt nu array.sumgebruiken in pure robijn, niet alleen Rails.


Antwoord 8, autoriteit 3%

Voor de diversiteit kun je dit ook doen als je array geen array van getallen is, maar eerder een array van objecten met eigenschappen die getallen zijn (bijvoorbeeld hoeveelheid):

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

Antwoord 9, autoriteit 3%

robijn 1.8.7 manier is de volgende:

array.inject(0, &:+) 

Antwoord 10

Ruby 2.4.0 is uitgebracht en heeft een Enumerable#summethode. Dus je kunt doen

array.sum

Voorbeelden uit de documenten:

{ 1 => 10, 2 => 20 }.sum {|k, v| k * v }  #=> 50
(1..10).sum                               #=> 55
(1..10).sum {|v| v * 2 }                  #=> 110

Antwoord 11

voor array met nulwaarden kunnen we compact doen en vervolgens de som injecteren
ex-

a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)

Antwoord 12

Ook [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

Antwoord 13

Methode 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

Methode 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 `+'

Methode 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 `+'

Methode 4:
Wanneer Array nul en lege waarden bevat, zal standaard, als u een van de bovenstaande functies gebruikt, alles verminderen, optellen, injecteren via de

TypeError: nul kan niet worden afgedwongen tot Integer

Je kunt dit oplossen door,

  [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

Methode 6:
eval

Evalueert de Ruby-expressie(s) in string.

 [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+

Antwoord 14

Als u zich golfachtig voelt, kunt u dat doen

eval [123,321,12389]*?+

Hiermee wordt een tekenreeks “123+321+12389” gemaakt en vervolgens wordt de functie eval gebruikt om de som uit te voeren. Dit is alleen voor golfdoeleinden, u mag het niet in de juiste code gebruiken.


Antwoord 15

Je kunt het ook op een gemakkelijke manier doen

def sum(numbers)
  return 0 if numbers.length < 1
  result = 0
  numbers.each { |num| result += num }
  result
end

Antwoord 16

U kunt .mapen .sumgebruiken als:

array.map { |e| e }.sum

Other episodes