Forum: Ruby Map more than one array at once

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
915aac3dfde2fb502ce415d77643a72d?d=identicon&s=25 Wil (Guest)
on 2007-07-19 18:11
(Received via mailing list)
Hi all,

I've been using Ruby for a while now, and have enjoyed it immensely.
However, I haven't yet found how to map more than one array at once.
The common example is calculating the dot product.  You'd need to
iterate through each array at the same time to multiply the elements.
However, map only operates on one list at a time.  I wanted to avoid
For Loops.  Therefore, I end up having to do something like this
instead:

def dot_prod(a,b)
  return 0 if a.length != b.length
  c = []
  a.each_with_index { |e, i| c << e * b[i] }
  c.inject { |e, t| t += e }
end

Ugly.  or use recursion:

def dot_prod(a, b)
  return 0 if a.length != b.length
  a.empty? ? 0 : a.first * b.first + dot_prod(a[1..-1], b[1..-1])
end

Better, but a map/inject solution would be desired.  Does anyone else
know of a way to iterate through two arrays without the use of an
index?  Or do people just roll their own multiple array map function?
0158871402c1ecfa57952e8a379cfd10?d=identicon&s=25 Daniel Lucraft (lucraft)
on 2007-07-19 18:17
Wil wrote:
> Hi all,
>
> Better, but a map/inject solution would be desired.  Does anyone else
> know of a way to iterate through two arrays without the use of an
> index?


def dot_prod(a, b)
  acc = 0
  a.zip(b) do |a1, b1|
    acc += a1*b1
  end
  acc
end

best,
Dan
94cc3e46cfc5bc361e409e2e884ecfa4?d=identicon&s=25 Drew Olson (dfg59)
on 2007-07-19 19:19
Wil wrote:
> Hi all,
>
> I've been using Ruby for a while now, and have enjoyed it immensely.
> However, I haven't yet found how to map more than one array at once.
> The common example is calculating the dot product.

Here's an example using inject, no need for a temp variable:

irb(main):001:0> def dot_prod a,b
irb(main):002:1>   a.zip(b).inject(0) do |dp,(a,b)|
irb(main):003:2*     dp + a*b
irb(main):004:2>   end
irb(main):005:1> end
=> nil
irb(main):006:0> dot_prod([1,2,3],[4,5,6])
=> 32
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2007-07-19 19:39
(Received via mailing list)
Alle giovedì 19 luglio 2007, Wil ha scritto:
> def dot_prod(a,b)
>   a.empty? ? 0 : a.first * b.first + dot_prod(a[1..-1], b[1..-1])
> end
>
> Better, but a map/inject solution would be desired.  Does anyone else
> know of a way to iterate through two arrays without the use of an
> index?  Or do people just roll their own multiple array map function?

require 'generator'

a = [1, 2, 3]
b = ['a', 'b', 'c']
c = [:x, :y, :z]

s = SyncEnumerator.new( a, b, c)
s.each{|i| puts "first: #{i[0]}, second: #{i[1]}, third: #{i[3]}"}
=>
first: 1, second: a, third: x
first: 2, second: b, third: y
first: 3, second: c, third: z

To define the dot product:

def dot_prod(a,b)
  raise ArgumentError unless a.size == b.size
  SyncEnumerator.new(a,b).inject(0){|res, i| res + i[0] * i[1]}
end

Stefano
This topic is locked and can not be replied to.