Tengo una serie de enteros.
Por ejemplo:
array = [123,321,12389]
¿Hay alguna forma agradable de obtener la suma de ellos?
Yo sé eso
sum = 0
array.each { |a| sum+=a }
trabajaría.
Tengo una serie de enteros.
Por ejemplo:
array = [123,321,12389]
¿Hay alguna forma agradable de obtener la suma de ellos?
Yo sé eso
sum = 0
array.each { |a| sum+=a }
trabajaría.
Respuestas:
Prueba esto:
array.inject(0){|sum,x| sum + x }
Ver la documentación enumerable de Ruby
(nota: el 0
caso base es necesario para que 0
se devuelva en una matriz vacía en lugar de nil
)
array.inject(:+)
es más eficiente.
array.inject(:+)
parece causar problemas en Ruby 1.8.6. Pueden aparecer excepciones "LocalJumpError: sin bloque".
array.sum
puede darte la suma de los valores de la matriz.
reduce
, que es un alias de inject
(como en array.reduce( :+ )
).
inject
lugar de reduce
.
O prueba la forma Ruby 1.9:
array.inject(0, :+)
Nota: el 0
caso base es necesario; de lo contrario nil
, se devolverá en matrices vacías:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
Es un poco más seguro. Se asegura de que si tiene una lista vacía, obtenga 0 en lugar de cero .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Si bien es equivalente a array.inject(0, :+)
, el término reducir está entrando en una lengua vernácula más común con el surgimiento de los modelos de programación MapReduce .
inyectar , reducir , plegar , acumular y comprimir son sinónimos de una clase de funciones de plegado . Considero que la coherencia en su código base es lo más importante, pero dado que varias comunidades tienden a preferir una palabra sobre otra, de todos modos es útil conocer las alternativas.
Para enfatizar el lenguaje de reducción de mapas, aquí hay una versión que es un poco más indulgente con lo que termina en esa matriz.
array.map(&:to_i).reduce(0, :+)
Algunas lecturas relevantes adicionales:
reduce
me dice más de lo que hace la función, pero inject
suena mucho mejor.
reduce
y map
como funciones de orden superior son anteriores a MapReduce. La inspiración va para otro lado. Y en el sentido de MapReduce, es una operación algo diferente a una simple reducción funcional, que tiene implicaciones sobre cómo se comunican las diferentes máquinas.
Alternativamente (solo para comparación), si tiene Rails instalado (en realidad solo ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
, o exigir a las de apoyo activo: require 'active_support/all'
. Más sobre esto aquí: API Docs
activesupport
sea una dependencia masiva para arrastrar a un proyecto para ir array.inject(:+)
a array.sum
.
require 'active_support/core_ext/enumerable'
sin el .rb
sufijo, ya que se agrega implícitamente.
Para Ruby> = 2.4.0 puede usar sum
de Enumerables.
[1, 2, 3, 4].sum
Es peligroso para las clases base mokeypatch. Si le gusta el peligro y utiliza una versión anterior de Ruby, puede agregar #sum
a la Array
clase:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Puede usar el método acertadamente nombrado Enumerable#sum
. Tiene muchas ventajas, inject(:+)
pero también hay algunas notas importantes para leer al final.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Este método no es equivalente a #inject(:+)
. Por ejemplo
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
También,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
Consulte esta respuesta para obtener más información sobre por qué sum
es así.
Ruby 2.4+ / Rails - array.sum
es decir[1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
oarray.reduce(:+)
* Nota: El #sum
método es una nueva adición a 2.4, por enumerable
lo que ahora podrá usarlo array.sum
en rubí puro, no solo en Rails.
Solo por el bien de la diversidad, también puede hacer esto si su matriz no es una matriz de números, sino una matriz de objetos que tienen propiedades que son números (por ejemplo, cantidad):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Ver otras respuestas.
map
a continuación inject
requiere que recorrer la matriz dos veces: una vez para crear una nueva matriz, el otro para resumir los miembros. Este método es un poco más detallado, pero también más eficiente.
ruby 1.8.7 way es el siguiente:
array.inject(0, &:+)
Simplemente puede usar:
example = [1,2,3]
example.inject(:+)
inject(:+)
pero esto no inject :+
?
Esto es suficiente
[1,2,3].inject('+')
Se lanza Ruby 2.4.0 y tiene un método Enumerable # sum . Entonces puedes hacer
array.sum
Ejemplos de los documentos:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
También permite [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
para una matriz con valores nulos podemos hacer compactos y luego inyectar la suma ex
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
Método 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
Método 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étodo 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étodo 4: cuando la matriz contiene valores nulos y vacíos, de manera predeterminada si utiliza alguna de las funciones anteriores, reduzca, sume, inyecte todo a través del
TypeError: nil no se puede convertir en Integer
Puedes superar esto,
[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étodo 6: eval
Evalúa las expresiones de Ruby en cadena.
[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+
Este es el camino más corto. Intentalo.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Esto funcionó bien para mí como nuevo desarrollador. Puede ajustar su rango de números cambiando los valores dentro de []
También puedes hacerlo de manera fácil
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Puede usar .map y .sum como:
array.map { |e| e }.sum
array.sum
array.sum