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 0
Basisfall wird benötigt, damit er 0
auf 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.sum
möglicherweise die Summe der Array-Werte.
reduce
eines Alias von inject
(wie in array.reduce( :+ )
).
inject
anstatt reduce
.
Oder probieren Sie Ruby 1.9:
array.inject(0, :+)
Hinweis: Der 0
Basisfall wird benötigt, andernfalls nil
wird 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:
reduce
erzähle mir mehr darüber, was die Funktion macht, inject
klingt aber viel cooler.
reduce
und map
wie 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
activesupport
eine 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 .rb
Suffix sein, da dies implizit hinzugefügt wird.
Für Ruby> = 2.4.0 können Sie sum
aus 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 #sum
der Array
Klasse 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 sum
dies so ist.
Ruby 2.4+ / Rails - array.sum
dh[1, 2, 3].sum # => 6
Ruby vor 2.4 - array.inject(:+)
oderarray.reduce(:+)
* Hinweis: Die #sum
Methode ist eine neue Ergänzung zu 2.4, enumerable
sodass Sie sie jetzt array.sum
in 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.
map
dann inject
mü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