What's the efficient way to multiply two arrays and get sum of multiplied values in Ruby?
Update
I've just updated benchmarks according to new comments. Following Joshua's comment, the inject method will gain a 25% speedup, see array walking without to_a
in the table below.
However since speed is the primary goal for the OP we have a new winner for the contest which reduces runtime from .34
to .22
in my benchmarks.
I still prefer inject
method because it's more ruby-ish, but if speed matters then the while loop seems to be the way.
New Answer
You can always benchmark all these answers, I did it for curiosity:
> ./matrix.rb
Rehearsal --------------------------------------------------------------
matrix method 1.500000 0.000000 1.500000 ( 1.510685)
array walking 0.470000 0.010000 0.480000 ( 0.475307)
array walking without to_a 0.340000 0.000000 0.340000 ( 0.337244)
array zip 0.590000 0.000000 0.590000 ( 0.594954)
array zip 2 0.500000 0.000000 0.500000 ( 0.509500)
while loop 0.220000 0.000000 0.220000 ( 0.219851)
----------------------------------------------------- total: 3.630000sec
user system total real
matrix method 1.500000 0.000000 1.500000 ( 1.501340)
array walking 0.480000 0.000000 0.480000 ( 0.480052)
array walking without to_a 0.340000 0.000000 0.340000 ( 0.338614)
array zip 0.610000 0.010000 0.620000 ( 0.625805)
array zip 2 0.510000 0.000000 0.510000 ( 0.506430)
while loop 0.220000 0.000000 0.220000 ( 0.220873)
Simple array walking wins, Matrix method is worse because it includes object instantiation. I think that if you want to beat the inject
while
method (to beat here means an order of magnitude fastest) you need to implement a C
extension and bind it in your ruby program.
Here it's the script I've used
#!/usr/bin/env ruby
require 'benchmark'
require 'matrix'
array_A = [1, 2, 1, 4, 5, 3, 2, 6, 5, 8, 9]
array_B = [3, 2, 4, 2, 5, 1, 3, 3, 7, 5, 4]
def matrix_method a1, a2
(Matrix.row_vector(a1) * Matrix.column_vector(a2)).element(0,0)
end
n = 100000
Benchmark.bmbm do |b|
b.report('matrix method') { n.times { matrix_method(array_A, array_B) } }
b.report('array walking') { n.times { (0...array_A.count).to_a.inject(0) {|r, i| r + array_A[i]*array_B[i]} } }
b.report('array walking without to_a') { n.times { (0...array_A.count).inject(0) {|r, i| r + array_A[i]*array_B[i]} } }
b.report('array zip') { n.times { array_A.zip(array_B).map{|i,j| i*j }.inject(:+) } }
b.report('array zip 2') { n.times { array_A.zip(array_B).inject(0) {|r, (a, b)| r + (a * b)} } }
b.report('while loop') do
n.times do
sum, i, size = 0, 0, array_A.size
while i < size
sum += array_A[i] * array_B[i]
i += 1
end
sum
end
end
end
How can I multiply two arrays in Ruby?
a.zip(b).map{|x, y| x * y}
This works because zip combines the two arrays into a single array of two element arrays. i.e.:
a = [3, 2, 1]
b = [1, 2, 3]
a.zip(b)
#=> [[3, 1], [2, 2], [1, 3]]
Then you use map to multiply the elements together. This is done by iterating through each two element array and multiplying one element by the other, with map returning the resulting array.
a.zip(b).map{|x, y| x * y}
#=> [3, 4, 3]
Calculate running total of multiple values in Ruby
UPDATE1:
it doesn't change anything.
You can still apply the codes.
(0..3).each do |value|
# First loop
values << [4444.33,0,333.444,0]
# Second loop
values << [3333.444,0,1123.44,5444]
# Third loop
values << [321112.4,443.3,0,4444]
# Here I need to add each array with the next one
values.transpose.map {|x| x.reduce(0, :+)}
end
1st ANSWER:
use mapping. just one line.
values.transpose.map {|x| x.reduce(0, :+)}
Ruby - Finding if any two numbers in an array if multiplied equal to a third number
I'd like to show a slightly more complicated version
def multiply_to (array,n)
numbers = array.map{|x|[x]}
pairs = []
for i in 0..numbers.length-1
pairs.concat numbers[i].product(array - numbers[i])
end
puts "#{pairs.count{|a,b|a * b == n} > 0}"
end
In languages that do not offer the functionality of Ruby, you need to do a little work.
We can store our combos in an array called pairs
We'd like to iterate over every number in the array. For all those numbers, we want to take the product of an array with that element and all the other numbers of the array.
This gives us all our combos of two numbers. We can test this method out as follows
multiply_to([4,7,9,13], 63)
=> true
Ruby - Sort array of arrays based on sum and object type
You can use:
Array#select
to extract the arrays based on a conditionEnumerable#grep_v
to extract non-integersArray#sum
to calculate the sums (usingto_f
for conversion)
elements.select do |ary|
ary.grep_v(Integer).sum(&:to_f) * 2 >= ary.sum(&:to_f)
end
#=> [[1, 2, "3", "4"], ["1", 2, 3, "4.0"], [1, 2, 3.0, 4.0, 5.0]]
You could also pass the to_f
-call to grep_v
, i.e. ary.grep_v(Integer, &:to_f).sum
but I prefer to have identical sum
-calls on both sides.
How do I perform vector addition in Ruby?
See the Vector class:
require "matrix"
x = Vector[100, 100]
y = Vector[2, 3]
print x + y
E:\Home> ruby t.rb
Vector[102, 103]
See vectorops for additional operations on vectors:
… the following operations work like expected
v1 = Vector[1,1,1,0,0,0]
v2 = Vector[1,1,1,1,1,1]
v1[0..3]
# -> Vector[1,1,1]
v1 += v2
# -> v1 == Vector[2,2,2,1,1,1]
v1[0..3] += v2[0..3]
# -> v1 == Vector[2,2,2,0,0,0]
v1 + 2
# -> Vector[3,3,3,1,1,1]
See also vectorops.
Related Topics
What Purpose Can Anonymous Modules Serve
Ruby Inserting Key, Value Elements in Hash
Rvm with Jruby 1.7.0 "Unknown Ruby Interpreter"
In Ruby, How to Remove Only 1 Match in an Array Easily
Using Ruby 2.0 on Amazon Opsworks
How to Remotely Inspect the Data in My Rediscloud Dbs
Why Does Using '-Webkit-Appearance: None' on a Select Option in Osx Make The Text Disappear
Fastest Way to Find a String into an Array of String
Is There an Easy-To-Use Ftp Library for Ruby
How to Upload a Local File to a Carrierwave Model
Generate String for Regex Pattern in Ruby
Sinatra + Heroku + Datamapper Deploy Issues with Dm-Sqlite-Adapter
Is There a Definitive Reference Document for Ruby Syntax
Ruby Block and Returning Something from Block
Ruby on Rails Triggers Update on Serialized Attribute Every Time