Am o matrice de numere întregi.
De exemplu:
array = [123,321,12389]
Există vreun mod frumos de a obține suma de ei?
Știu, că
sum = 0
array.each { |a| sum+=a }
ar lucra.
Încercați acest lucru:
array.inject(0){|sum,x| sum + x }
Vezi Ruby's Enumerable Documentația
(notă: 0
caz de bază este necesar, astfel încât 0
va fi returnat într-o matrice goală în loc de "zero")
array.reduce(0, :+)
În timp ce echivalentul a matrice.injectează - (0, :+)
, termen lung reducerea intră într-o mai comune autohton cu creșterea de MapReduce modele de programare.
injectați, reducerea, ori, acumula și comprese sunt sinonime ca o clasă de pliere funcții. Am găsi coerența pe bază de cod cele mai importante, dar din diverse comunități tind să prefere un singur cuvânt peste alta, este totuși util să se cunoască alternative.
Pentru a sublinia map-reduce verbiaj, aici e o versiune care este un pic mai iertator pe ce se termină în matrice.
array.map(&:to_i).reduce(0, :+)
Unele suplimentare relevante lectură:
Pentru Ruby >=2.4.0 puteți folosi "sumă" de la Enumerables.
[1, 2, 3, 4].sum
Este periculos să mokeypatch clase de bază. Dacă îți place pericolul și utilizează o versiune mai veche de Ruby, ai putea adauga #sum
a de "Matrice" clasa:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Puteți folosi pe bună dreptate numit metoda Enumerable#sum
. Ea are o mulțime de avantaje față de inject(:+)
dar există unele note importante pentru a citi de la sfârșitul la fel de bine.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Această metodă nu este echivalent cu #inject(:+)
. De exemplu
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
De asemenea,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
A se vedea acest răspuns pentru mai multe informații despre ce " sum " este ca aceasta.
Ruby 2.4+ / Șine - matrice.sum
de exemplu [1, 2, 3].suma # => 6
Ruby pre 2.4 - matrice.injectați (:+) " sau " matrice.reduce(:+)
*Nota: #sum
metoda este un nou plus față de 2.4 pentru enumerable` astfel încât veți fi acum posibilitatea de a folosi matrice.suma în pură ruby, nu doar Șine.
Doar de dragul diversității, de asemenea, puteți face acest lucru dacă matricea nu este o serie de numere, ci mai degrabă o serie de obiecte care au proprietăți care sunt numerele (de exemplu, suma):
array.inject(0){|sum,x| sum + x.amount}
Permite, de asemenea, [1,2].suma{|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
Dacă vă simțiți golfy, puteți face
eval([123,321,12389]*?+)
Acest lucru va crea un șir de caractere "123+321+12389" și apoi utilizați funcția eval pentru a face suma. Acest lucru este numai pentru golf scop, tu nu ar trebui să-l folosească în cod.
Metoda 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
Metoda 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 `+'
Metoda 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 `+'
Metoda 4: Când Matrice conține un zero și valorile goale, în mod implicit dacă folosiți funcțiile de mai sus reduce, suma, injectați totul va prin
TypeError: nil poate't fi constrâns în Întreg
Puteți depăși acest lucru,
[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
Metoda 6: evaluare
Evaluează Ruby exprimare(s) în șir.
[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+