Comment puis-je utiliser cette méthode pour additionner un attribut à partir d'un objet. Mon tableau [product1, product2] Je veux additionner product1.price + product2.price. Est-il possible d'utiliser array.inject (: +)?
Pablo Cantero
7
Vous pouvez utiliser une astuce similaire avec la méthode map: array.map (&: price) .inject (: +)
markquezada
100
array.map(&:price).inject(0, :+)est un peu plus sûr. Il s'assure que si vous avez une liste vide, vous obtenez 0 au lieu de zéro .
johnf
11
en utilisant array.map (...). inject (...) est inefficace, vous parcourrez toutes les données deux fois. Essayez array.inject(0) { |sum, product| sum += product.price }
Bien qu'équivalent à array.inject(0, :+), le terme réduire entre dans une langue vernaculaire plus courante avec l'essor des modèles de programmation MapReduce .
injecter , réduire , plier , accumuler et compresser sont tous synonymes d'une classe de fonctions de pliage . Je trouve la cohérence dans votre base de code la plus importante, mais comme diverses 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 de réduction de carte, voici une version qui est un peu plus indulgente sur ce qui se retrouve dans ce tableau.
Je suis d'accord, reduceme dit plus sur ce que fait la fonction, mais injectsonne beaucoup plus cool.
everett1992
1
D'accord avec le dernier commentaire, tu m'as donné la meilleure réponse.
Jerska
1
Le seul commentaire que je ferais est que reduceet mapcomme les fonctions d'ordre supérieur sont antérieures à MapReduce. L'inspiration va dans l'autre sens. Et dans le sens MapReduce, il s'agit d'une opération quelque peu différente d'une simple réduction fonctionnelle, ayant des implications sur la façon dont les différentes machines communiquent.
acjay
Ken Iverson a introduit l'opérateur / appelé "opérateur de réduction" dans le langage de programmation APL. Source: Iverson, Kenneth. 1962. Un langage de programmation. Wiley. Une autre source: "Notation as a Tool of Thought", 1979 ACM Turing Award Lecture, Kenneth E. Iverson, dl.acm.org/ft_gateway.cfm?id=1283935&type=pdf
Fernando Pelliccioni
112
Alternativement (juste pour comparaison), si vous avez installé Rails (en fait juste ActiveSupport):
Les nouvelles versions d'Activesupport ne chargent pas réellement toutes les extensions par défaut. Vous voudrez soit juste besoin du module de somme: require 'active_support/core_ext/enumerable.rb', ou besoin tout soutien actif: require 'active_support/all'. Pour en savoir plus, cliquez ici: API Docs
dcashman
2
Peu importe, c'est activesupportune dépendance massive à glisser dans un projet pour aller de array.inject(:+)à array.sum.
meagar
1
Nitpick à un autre bon commentaire: il devrait être require 'active_support/core_ext/enumerable'sans le .rbsuffixe, car il est ajouté implicitement.
Per Lundberg
72
Pour Ruby> = 2.4.0, vous pouvez utiliser sumdepuis Enumerables.
[1,2,3,4].sum
Il est dangereux de mokeypatch les classes de base. Si vous aimez le danger et utilisez une ancienne version de Ruby, vous pouvez ajouter #sumà la Arrayclasse:
classArraydef sum
inject(0){|sum, x| sum + x }endend
Monkeypatching les classes de base n'est pas sympa.
user3467349
1
Le point qu'il fait valoir est que vous n'avez pas besoin de faire le patch de singe pour Ruby> = 2.4, et que le patch de singe est dangereux, et que vous pouvez maintenant additionner les énumérables en natif, mais il existe également un moyen de rétroporter la fonctionnalité.
Peter H. Boling du
Voté car votre implémentation retourne nil sur des tableaux vides.
Eldritch Conundrum
45
Nouveau pour Ruby 2.4.0
Vous pouvez utiliser la méthode bien nommée Enumerable#sum. Il présente de nombreux avantages, inject(:+)mais il y a également des notes importantes à lire à la fin.
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 sumest-ce comme ça.
* Remarque: La #summéthode est un nouvel ajout à la version 2.4 pour enumerableque vous puissiez désormais l'utiliser array.sumen rubis pur, pas seulement Rails.
Ruby 2.4.0 est sorti aujourd'hui avec cette fonctionnalité incluse! 🎉
amoebe
@amoebe vous avez raison! Heureux de voir cette fonctionnalité utile incluse.
récupérer le
19
Dans un souci de diversité, vous pouvez également le faire si votre tableau n'est pas un tableau de nombres, mais plutôt un tableau d'objets qui ont des propriétés qui sont des nombres (par exemple quantité):
Cela équivaut à faire: array.map(&:amount).inject(0, :+). Voir d'autres réponses.
Richard Jones
4
D'une certaine manière, oui. Cependant, en utilisant mapalors injectvous devez faire une boucle à travers le réseau deux fois: une fois pour créer un nouveau tableau, l'autre pour sommer les membres. Cette méthode est légèrement plus verbeuse, mais aussi plus efficace.
# 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
Cela va créer une chaîne "123 + 321 + 12389" puis utiliser la fonction eval pour faire la somme. C'est uniquement à des fins de golf , vous ne devez pas l'utiliser dans le bon code.
[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 un nil et des valeurs vides, par défaut si vous utilisez l'une des fonctions ci-dessus, réduisez, additionnez, injectez tout sera par le
TypeError: aucun ne peut être contraint en entier
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 les expressions Ruby dans une 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+
array.sum
Réponses:
Essaye ça:
Voir la documentation énumérable de Ruby
(note: le
0
cas de base est nécessaire pour qu'il0
soit retourné sur un tableau vide au lieu denil
)la source
array.inject(:+)
est plus efficace.array.inject(:+)
semble causer des problèmes dans Ruby 1.8.6 Exceptions "LocalJumpError: aucun bloc donné" pourrait apparaître.array.sum
peut vous donner la somme des valeurs du tableau.reduce
, qui est un alias deinject
(comme dansarray.reduce( :+ )
).inject
plutôt quereduce
.Ou essayez la méthode Ruby 1.9:
Remarque: le
0
cas de base est nécessaire sinonnil
il sera retourné sur des tableaux vides:la source
array.map(&:price).inject(0, :+)
est un peu plus sûr. Il s'assure que si vous avez une liste vide, vous obtenez 0 au lieu de zéro .array.inject(0) { |sum, product| sum += product.price }
Bien qu'équivalent à
array.inject(0, :+)
, le terme réduire entre dans une langue vernaculaire plus courante avec l'essor des modèles de programmation MapReduce .injecter , réduire , plier , accumuler et compresser sont tous synonymes d'une classe de fonctions de pliage . Je trouve la cohérence dans votre base de code la plus importante, mais comme diverses 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 de réduction de carte, voici une version qui est un peu plus indulgente sur ce qui se retrouve dans ce tableau.
Quelques lectures pertinentes supplémentaires:
la source
reduce
me dit plus sur ce que fait la fonction, maisinject
sonne beaucoup plus cool.reduce
etmap
comme les fonctions d'ordre supérieur sont antérieures à MapReduce. L'inspiration va dans l'autre sens. Et dans le sens MapReduce, il s'agit d'une opération quelque peu différente d'une simple réduction fonctionnelle, ayant des implications sur la façon dont les différentes machines communiquent.Alternativement (juste pour comparaison), si vous avez installé Rails (en fait juste ActiveSupport):
la source
require 'active_support/core_ext/enumerable.rb'
, ou besoin tout soutien actif:require 'active_support/all'
. Pour en savoir plus, cliquez ici: API Docsactivesupport
une dépendance massive à glisser dans un projet pour aller dearray.inject(:+)
àarray.sum
.require 'active_support/core_ext/enumerable'
sans le.rb
suffixe, car il est ajouté implicitement.Pour Ruby> = 2.4.0, vous pouvez utiliser
sum
depuis Enumerables.Il est dangereux de mokeypatch les classes de base. Si vous aimez le danger et utilisez une ancienne version de Ruby, vous pouvez ajouter
#sum
à laArray
classe:la source
Nouveau pour Ruby 2.4.0
Vous pouvez utiliser la méthode bien nommée
Enumerable#sum
. Il présente de nombreux avantages,inject(:+)
mais il y a également des notes importantes à lire à la fin.Exemples
Gammes
Tableaux
Note importante
Cette méthode n'est pas équivalente à
#inject(:+)
. Par exempleAussi,
Voir cette réponse pour plus d'informations sur pourquoi
sum
est-ce comme ça.la source
Ruby 2.4+ / Rails -
array.sum
ie[1, 2, 3].sum # => 6
Ruby pre 2.4 -
array.inject(:+)
ouarray.reduce(:+)
* Remarque: La
#sum
méthode est un nouvel ajout à la version 2.4 pourenumerable
que vous puissiez désormais l'utiliserarray.sum
en rubis pur, pas seulement Rails.la source
Dans un souci de diversité, vous pouvez également le faire si votre tableau n'est pas un tableau de nombres, mais plutôt un tableau d'objets qui ont des propriétés qui sont des nombres (par exemple quantité):
la source
array.map(&:amount).inject(0, :+)
. Voir d'autres réponses.map
alorsinject
vous devez faire une boucle à travers le réseau deux fois: une fois pour créer un nouveau tableau, l'autre pour sommer les membres. Cette méthode est légèrement plus verbeuse, mais aussi plus efficace.ruby 1.8.7 way est le suivant:
la source
Vous pouvez simplement utiliser:
la source
inject(:+)
mais cela ne fonctionne pasinject :+
?C'est assez
[1,2,3].inject('+')
la source
Ruby 2.4.0 est sorti, et il a une méthode de somme Enumerable # . Vous pouvez donc faire
Exemples tirés de la documentation:
la source
Permet également
[1,2].sum{|x| x * 2 } == 6
:la source
pour un tableau avec des valeurs nulles, nous pouvons faire compact, puis injecter la somme ex-
la source
Fonctionne également pour les plages ... par conséquent,
la source
Si vous vous sentez golfé, vous pouvez le faire
Cela va créer une chaîne "123 + 321 + 12389" puis utiliser la fonction eval pour faire la somme. C'est uniquement à des fins de golf , vous ne devez pas l'utiliser dans le bon code.
la source
Méthode 1:
Méthode 2:
Méthode 3:
Méthode 4: lorsque Array contient un nil et des valeurs vides, par défaut si vous utilisez l'une des fonctions ci-dessus, réduisez, additionnez, injectez tout sera par le
Vous pouvez surmonter cela en,
Méthode 6: eval
Évalue les expressions Ruby dans une chaîne.
la source
3 façons de faire la somme des tableaux
1)
array.inject(0){|sum,x| sum + x }
2)
array.inject('+')
3)
array.join('+')
la source
Ou vous pouvez essayer cette méthode:
la source
C'est le chemin le plus court. Essayez-le.
array.inject :+
la source
* 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 []
la source
Vous pouvez également le faire de manière simple
la source
Vous pouvez utiliser .map et .sum comme:
la source
array.sum