Realizando una aplicación en Rails necesitaba sumar varios atributos de los objetos almacenados en un array. El problema es que cuando se trata de sumar un único atributo, se suele utilizar el método inject:
total = mi_array.inject { |sum, obj| sum + obj.value }
pero en este caso no me terminaba de convecer estar llamando al método inject tantas veces como atributos quisiera sumar, así que en teoría la solución pasaría por iterar sobre el array e ir sumando:
var1 = 0 var2 = 0 var3 = 0 ... mi_array.each do |obj| var1 += obj.value1 var2 += obj.value2 var3 += obj.value3 ... end
Funcionar, funcionaba, pero digamos que el código quedaba algo feo, así que para seguir trasteando, intenté encontrar una solución más 'ruby' y esto fue lo que hice:
class Array
def accumulate(fields)
results = fields.dup
self.each do |obj|
fields.each_key do |key|
results[key] += obj.send(key) if obj.respond_to?(key)
end
end
results
end
end
Ahora bastaba con llamar al método accumulate sobre el array de objetos e indicar qué atributos quería sumar para obtener un hash con los resultados:
# la lista de objetos
foos = [
OpenStruct.new(:foo => 1, :bar => 2, :foobar => 3),
OpenStruct.new(:foo => 3, :bar => 4, :foobar => 5),
OpenStruct.new(:foo => 5, :bar => 6, :foobar => 7)
]
foos.accumulate(:foo =>; 0, :bar => 0, :foobar => 0)
# {:foo=>9, :bar=>12, :foobar=>15}