Ho una matrice di numeri interi.
Per esempio:
array = [123,321,12389]
C'è un modo carino per ottenerne la somma?
Lo so
sum = 0
array.each { |a| sum+=a }
funzionerebbe.
Ho una matrice di numeri interi.
Per esempio:
array = [123,321,12389]
C'è un modo carino per ottenerne la somma?
Lo so
sum = 0
array.each { |a| sum+=a }
funzionerebbe.
Risposte:
Prova questo:
array.inject(0){|sum,x| sum + x }
Vedi la documentazione enumerabile di Ruby
(nota: il 0
caso base è necessario in modo che 0
venga restituito su un array vuoto anziché nil
)
array.inject(:+)
è più efficiente.
array.inject(:+)
sembra causare problemi in Ruby 1.8.6 Potrebbero apparire eccezioni "LocalJumpError: nessun blocco fornito".
array.sum
potrebbe darti la somma dei valori dell'array.
reduce
, che è un alias di inject
(come in array.reduce( :+ )
).
inject
anziché reduce
.
Oppure prova il modo Ruby 1.9:
array.inject(0, :+)
Nota: il 0
caso base è necessario altrimenti nil
verrà restituito su array vuoti:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
è un po 'più sicuro. Si assicura che se si dispone di un elenco vuoto si ottiene 0 anziché zero .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Sebbene equivalente a array.inject(0, :+)
, il termine ridurre sta entrando in un vernacolo più comune con l'ascesa dei modelli di programmazione MapReduce .
iniettare , ridurre , piegare , accumulare e comprimere sono tutti sinonimi di una classe di funzioni di piegatura . Trovo che la coerenza tra la tua base di codice sia la più importante, ma poiché varie comunità tendono a preferire una parola rispetto a un'altra, è comunque utile conoscere le alternative.
Per enfatizzare la verbosità della riduzione della mappa, ecco una versione che è un po 'più tollerante su ciò che finisce in quella matrice.
array.map(&:to_i).reduce(0, :+)
Alcune letture pertinenti aggiuntive:
reduce
mi dice di più su ciò che fa la funzione, ma inject
suona molto più fresco.
reduce
e map
poiché le funzioni di ordine superiore precedono MapReduce. L'ispirazione va dall'altra parte. E nel senso di MapReduce, è un'operazione leggermente diversa da una semplice riduzione funzionale, con implicazioni per il modo in cui comunicano macchine diverse.
In alternativa (solo per confronto), se hai installato Rails (in realtà solo ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
o richiedono a tutte le sostegno attivo: require 'active_support/all'
. Maggiori informazioni qui: API Docs
activesupport
è una massiccia dipendenza trascinare in un progetto per andare da array.inject(:+)
a array.sum
.
require 'active_support/core_ext/enumerable'
senza il .rb
suffisso, poiché è stato aggiunto implicitamente.
Per Ruby> = 2.4.0 è possibile utilizzare sum
da Enumerables.
[1, 2, 3, 4].sum
È pericoloso classificare le classi base. Se ti piace il pericolo e usi una versione precedente di Ruby, potresti aggiungere #sum
alla Array
classe:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
È possibile utilizzare il metodo con nome appropriato Enumerable#sum
. Ha molti vantaggi, inject(:+)
ma alla fine ci sono anche alcune note importanti da leggere.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Questo metodo non è equivalente a #inject(:+)
. Per esempio
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
Anche,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
Vedi questa risposta per maggiori informazioni sul perché sum
è così.
Ruby 2.4+ / Rails - ad array.sum
es[1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
oppurearray.reduce(:+)
* Nota: il #sum
metodo è una nuova aggiunta alla versione 2.4 per enumerable
cui ora sarai in grado di utilizzare array.sum
il rubino puro, non solo Rails.
Solo per motivi di diversità, puoi anche farlo se la tua matrice non è una matrice di numeri, ma piuttosto una matrice di oggetti che hanno proprietà che sono numeri (ad esempio quantità):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Vedi altre risposte
map
quindi inject
di passare in rassegna l'array due volte: una volta per creare un nuovo array, l'altro per sommare i membri. Questo metodo è leggermente più dettagliato, ma anche più efficiente.
ruby 1.8.7 way è il seguente:
array.inject(0, &:+)
Puoi semplicemente usare:
example = [1,2,3]
example.inject(:+)
inject(:+)
ma non funziona inject :+
?
È abbastanza
[1,2,3].inject('+')
Ruby 2.4.0 viene rilasciato e ha un metodo Enumerable # sum . Quindi puoi farlo
array.sum
Esempi dai documenti:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
Inoltre consente di [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
per array con valori nulli possiamo fare compatto e quindi iniettare la somma ex-
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
Metodo 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
Metodo 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 `+'
Metodo 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 `+'
Metodo 4: Quando l'array contiene valori nulli e vuoti, per impostazione predefinita se si utilizza una delle funzioni sopra, ridurre, sommare, iniettare tutto ciò che
TypeError: zero non può essere forzato in Integer
Puoi superare questo,
[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
Metodo 6: eval
Valuta le espressioni Ruby nella stringa.
[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+
Questo è il modo più breve. Provalo.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Questo ha funzionato bene per me come nuovo sviluppatore. È possibile regolare l'intervallo di numeri modificando i valori all'interno di []
Puoi anche farlo in modo semplice
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Puoi usare .map e .sum come:
array.map { |e| e }.sum
array.sum
array.sum