Ich habe eine Reihe von ganzen Zahlen.
Zum Beispiel:
array = [123,321,12389]
Gibt es eine gute Möglichkeit, die Summe zu ermitteln?
Ich weiß das
sum = 0
array.each { |a| sum+=a }
würde funktionieren.
Ich habe eine Reihe von ganzen Zahlen.
Zum Beispiel:
array = [123,321,12389]
Gibt es eine gute Möglichkeit, die Summe zu ermitteln?
Ich weiß das
sum = 0
array.each { |a| sum+=a }
würde funktionieren.
Antworten:
Versuche dies:
array.inject(0){|sum,x| sum + x }
Siehe Rubys Aufzählungsdokumentation
(Hinweis: Der 0Basisfall wird benötigt, damit er 0auf einem leeren Array zurückgegeben wird. nil)
array.inject(:+)ist effizienter.
array.inject(:+)scheint Probleme in Ruby 1.8.6 zu verursachen. Ausnahmen "LocalJumpError: kein Block angegeben" könnten auftauchen.
array.summöglicherweise die Summe der Array-Werte.
reduceeines Alias von inject(wie in array.reduce( :+ )).
injectanstatt reduce.
Oder probieren Sie Ruby 1.9:
array.inject(0, :+)
Hinweis: Der 0Basisfall wird benötigt, andernfalls nilwird er auf leeren Arrays zurückgegeben:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)ist ein bisschen sicherer. Es stellt sicher, dass Sie bei einer leeren Liste 0 anstelle von Null erhalten .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Während entspricht array.inject(0, :+), der Begriff reduce eine üblichere Umgangssprache mit dem Anstieg des eintritt MapReduce Programmiermodelle .
Injizieren , Reduzieren , Falten , Akkumulieren und Komprimieren sind synonym eine Klasse von Faltfunktionen . Ich finde Konsistenz in Ihrer Codebasis am wichtigsten, aber da verschiedene Communities dazu neigen, ein Wort einem anderen vorzuziehen, ist es dennoch nützlich, die Alternativen zu kennen.
Um die kartenreduzierte Sprache hervorzuheben, ist hier eine Version, die etwas verzeihender ist, was in diesem Array endet.
array.map(&:to_i).reduce(0, :+)
Einige zusätzliche relevante Lektüre:
reduceerzähle mir mehr darüber, was die Funktion macht, injectklingt aber viel cooler.
reduceund mapwie Funktionen höherer Ordnung MapReduce predate. Die Inspiration läuft in die andere Richtung. Im Sinne von MapReduce handelt es sich um eine etwas andere Operation als eine einfache Funktionsreduzierung, die Auswirkungen auf die Kommunikation verschiedener Maschinen hat.
Alternativ (nur zum Vergleich), wenn Sie Rails installiert haben (eigentlich nur ActiveSupport):
require 'activesupport'
array.sum
activesupporteine massive Abhängigkeit ist, um in ein Projekt zu ziehen, von array.inject(:+)dem aus zu gehen array.sum.
require 'active_support/core_ext/enumerable'ohne das .rbSuffix sein, da dies implizit hinzugefügt wird.
Für Ruby> = 2.4.0 können Sie sumaus Enumerables verwenden.
[1, 2, 3, 4].sum
Es ist gefährlich, Basisklassen zu mokeypatchen. Wenn Sie Gefahr mögen und eine ältere Version von Ruby verwenden, können Sie #sumder ArrayKlasse Folgendes hinzufügen :
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Sie können die treffend benannte Methode verwenden Enumerable#sum. Es hat viele Vorteile gegenüber, inject(:+)aber am Ende gibt es auch einige wichtige Hinweise zu lesen.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Diese Methode ist nicht gleichbedeutend mit #inject(:+). Zum Beispiel
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
Ebenfalls,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
In dieser Antwort finden Sie weitere Informationen dazu, warum sumdies so ist.
Ruby 2.4+ / Rails - array.sumdh[1, 2, 3].sum # => 6
Ruby vor 2.4 - array.inject(:+)oderarray.reduce(:+)
* Hinweis: Die #sumMethode ist eine neue Ergänzung zu 2.4, enumerablesodass Sie sie jetzt array.sumin reinem Rubin verwenden können, nicht nur in Rails.
Nur aus Gründen der Vielfalt können Sie dies auch tun, wenn Ihr Array kein Array von Zahlen ist, sondern ein Array von Objekten mit Eigenschaften, die Zahlen sind (z. B. Betrag):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+). Siehe andere Antworten.
mapdann injectmüssen Sie zweimal durch die Array - Schleife: einmal ein neues Array zu erstellen, die andere die Mitglieder zu summieren. Diese Methode ist etwas ausführlicher, aber auch effizienter.
Ruby 1.8.7 Weg ist der folgende:
array.inject(0, &:+)
Sie können einfach verwenden:
example = [1,2,3]
example.inject(:+)
inject(:+)aber das nicht inject :+?
Das ist genug
[1,2,3].inject('+')
Ruby 2.4.0 ist veröffentlicht und verfügt über eine Enumerable # sum- Methode. So können Sie tun
array.sum
Beispiele aus den Dokumenten:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
Ermöglicht auch [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
Für Arrays mit Nullwerten können wir kompakt machen und dann die Summe ex- injizieren
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
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: Wenn das Array null und leere Werte enthält, reduzieren, summieren und injizieren Sie standardmäßig alles, wenn Sie eine der oben genannten Funktionen verwenden
TypeError: nil kann nicht in Integer gezwungen werden
Sie können dies überwinden, indem Sie
[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: Bewertung
Wertet die Ruby-Ausdrücke in der Zeichenfolge aus.
[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+
Dies ist der kürzeste Weg. Versuch es.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Das hat für mich als neuen Entwickler gut funktioniert. Sie können Ihren Nummernkreis anpassen, indem Sie die Werte in [] ändern.
Sie können es auch auf einfache Weise tun
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Sie können .map und .sum wie folgt verwenden :
array.map { |e| e }.sum
array.sum
array.sum