Wie kann ich auf diese Weise ein Attribut aus einem Objekt summieren? Mein Array [Produkt1, Produkt2] Ich möchte Produkt1.Preis + Produkt2.Preis summieren. Ist es möglich, array.inject (: +) zu verwenden?
Pablo Cantero
7
Sie können einen ähnlichen Trick mit der Kartenmethode verwenden: array.map (&: price) .inject (: +)
markquezada
100
array.map(&:price).inject(0, :+)ist ein bisschen sicherer. Es stellt sicher, dass Sie bei einer leeren Liste 0 anstelle von Null erhalten .
Johnf
11
Wenn Sie array.map (...) verwenden, ist injizieren (...) ineffizient. Sie werden alle Daten zweimal durchlaufen. Versuchen Sie array.inject(0) { |sum, product| sum += product.price }
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.
Ich stimme zu, reduceerzähle mir mehr darüber, was die Funktion macht, injectklingt aber viel cooler.
everett1992
1
Stimmen Sie dem letzten Kommentar zu, Sie haben mir die beste Antwort gegeben.
Jerska
1
Der einzige Kommentar , den ich machen würde , ist , dass 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.
Acjay
Ken Iverson führte den Operator / "Reduktionsoperator" in der Programmiersprache APL ein. Quelle: Iverson, Kenneth. 1962. Eine Programmiersprache. Wiley. Eine andere Quelle: "Notation als Werkzeug des Denkens", 1979 ACM Turing Award Lecture, Kenneth E. Iverson, dl.acm.org/ft_gateway.cfm?id=1283935&type=pdf
Fernando Pelliccioni
112
Alternativ (nur zum Vergleich), wenn Sie Rails installiert haben (eigentlich nur ActiveSupport):
Neuere Versionen von activesupport laden standardmäßig nicht alle Erweiterungen. Sie möchten entweder nur das Summenmodul benötigen: require 'active_support/core_ext/enumerable.rb'oder die gesamte aktive Unterstützung : require 'active_support/all'. Mehr dazu hier: API Docs
dcashman
2
Es ist egal, dass dies activesupporteine massive Abhängigkeit ist, um in ein Projekt zu ziehen, von array.inject(:+)dem aus zu gehen array.sum.
Meagar
1
Nitpick zu einem ansonsten guten Kommentar: Es sollte require 'active_support/core_ext/enumerable'ohne das .rbSuffix sein, da dies implizit hinzugefügt wird.
Per Lundberg
72
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 :
classArraydef sum
inject(0){|sum, x| sum + x }endend
Der Punkt, den er macht, ist, dass Sie den Monkey Patch für Ruby> = 2.4 nicht ausführen müssen und dass das Patchen von Affen gefährlich ist und dass Sie jetzt Enumerables nativ summieren können, aber es gibt auch eine Möglichkeit, die Funktionalität zurück zu portieren.
Peter H. Boling
Downvoted, da Ihre Implementierung bei leeren Arrays null zurückgibt.
Eldritch Conundrum
45
Neu für Ruby 2.4.0
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.
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)
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.
Ruby 2.4.0 wurde heute mit dieser Funktion veröffentlicht! 🎉
Amöbe
@amoebe du bist richtig! Ich bin froh, dass diese nützliche Funktion enthalten ist.
Sammeln Sie
19
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):
Dies entspricht : array.map(&:amount).inject(0, :+). Siehe andere Antworten.
Richard Jones
4
In gewisser Weise ja. Allerdings verwenden 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.
# http://madeofcode.com/posts/74-ruby-core-extension-array-sumclassArraydef 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 }endendend
Dadurch wird eine Zeichenfolge "123 + 321 + 12389" erstellt und anschließend die Funktion eval mit der Funktion eval erstellt. Dies ist nur zum Golfen gedacht , Sie sollten es nicht im richtigen Code verwenden.
[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+
array.sum
Antworten:
Versuche dies:
Siehe Rubys Aufzählungsdokumentation
(Hinweis: Der
0
Basisfall wird benötigt, damit er0
auf einem leeren Array zurückgegeben wird.nil
)quelle
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 voninject
(wie inarray.reduce( :+ )
).inject
anstattreduce
.Oder probieren Sie Ruby 1.9:
Hinweis: Der
0
Basisfall wird benötigt, andernfallsnil
wird er auf leeren Arrays zurückgegeben:quelle
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 }
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.
Einige zusätzliche relevante Lektüre:
quelle
reduce
erzähle mir mehr darüber, was die Funktion macht,inject
klingt aber viel cooler.reduce
undmap
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):
quelle
require 'active_support/core_ext/enumerable.rb'
oder die gesamte aktive Unterstützung :require 'active_support/all'
. Mehr dazu hier: API Docsactivesupport
eine massive Abhängigkeit ist, um in ein Projekt zu ziehen, vonarray.inject(:+)
dem aus zu gehenarray.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.Es ist gefährlich, Basisklassen zu mokeypatchen. Wenn Sie Gefahr mögen und eine ältere Version von Ruby verwenden, können Sie
#sum
derArray
Klasse Folgendes hinzufügen :quelle
Neu für Ruby 2.4.0
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.Beispiele
Bereiche
Arrays
Wichtige Notiz
Diese Methode ist nicht gleichbedeutend mit
#inject(:+)
. Zum BeispielEbenfalls,
In dieser Antwort finden Sie weitere Informationen dazu, warum
sum
dies so ist.quelle
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 jetztarray.sum
in reinem Rubin verwenden können, nicht nur in Rails.quelle
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):
quelle
array.map(&:amount).inject(0, :+)
. Siehe andere Antworten.map
danninject
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:
quelle
Sie können einfach verwenden:
quelle
inject(:+)
aber das nichtinject :+
?Das ist genug
[1,2,3].inject('+')
quelle
Ruby 2.4.0 ist veröffentlicht und verfügt über eine Enumerable # sum- Methode. So können Sie tun
Beispiele aus den Dokumenten:
quelle
Ermöglicht auch
[1,2].sum{|x| x * 2 } == 6
:quelle
Für Arrays mit Nullwerten können wir kompakt machen und dann die Summe ex- injizieren
quelle
Funktioniert auch für Bereiche ... daher
quelle
Wenn Sie sich golfig fühlen, können Sie tun
Dadurch wird eine Zeichenfolge "123 + 321 + 12389" erstellt und anschließend die Funktion eval mit der Funktion eval erstellt. Dies ist nur zum Golfen gedacht , Sie sollten es nicht im richtigen Code verwenden.
quelle
Methode 1:
Methode 2:
Methode 3:
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
Sie können dies überwinden, indem Sie
Methode 6: Bewertung
Wertet die Ruby-Ausdrücke in der Zeichenfolge aus.
quelle
3 Möglichkeiten, wie wir die Summe der Arrays machen können
1)
array.inject(0){|sum,x| sum + x }
2)
array.inject('+')
3)
array.join('+')
quelle
Oder Sie können diese Methode ausprobieren:
quelle
Dies ist der kürzeste Weg. Versuch es.
array.inject :+
quelle
* Das hat für mich als neuen Entwickler gut funktioniert. Sie können Ihren Nummernkreis anpassen, indem Sie die Werte in [] ändern.
quelle
Sie können es auch auf einfache Weise tun
quelle
Sie können .map und .sum wie folgt verwenden :
quelle
array.sum