Array collect - nil can't be coerced into Float (TypeError)

I have this simple program that has a problem that I just can’t find a
solution to:


class MyArray

def count
a = [50.1,52.0,55.0,60.0]
b = [0.24,0.1,0.29,0.9]
i = 0
c = []
while i <= 4 do
puts c = b.collect {|x| x * a[i]}
i += 1
end

end
end

number = MyArray.new
number.count


I want each element of array ‘b’ to be multiplied by each element of ‘a’
and return a vector, ‘c’ with 16 rows.

this code works, but I get an error that says:
ArrayInsert.rb:9:in *': nil can't be coerced into Float (TypeError) from ArrayInsert.rb:9:incount’
from ArrayInsert.rb:9:in collect' from ArrayInsert.rb:9:incount’
from ArrayInsert.rb:17

I don’t understand where ‘nil’ is coming from. Can someone help me with
this one? Thank you.

On Wednesday 11 June 2008, Jason L. wrote:

while i <= 4 do

I want each element of array ‘b’ to be multiplied by each element of ‘a’
this one? Thank you.
Array indexes go from 0 to the number of elements of the array minus
one. In
your code, you allow i to be 4 (because you put <= in the while
condition),
then use i to access the elements of the array a. Since a has four
elements,
the last non-nil element has index 3. When i is 4, a[i] will return nil,
giving the error you see.

I hope this helps

Stefano

On Wed, Jun 11, 2008 at 9:37 PM, Jason L.
[email protected] wrote:

while i <= 4 do
this should be i < 4, however …
puts c = b.collect {|x| x * a[i]}
i += 1
end

end
end

> I don't understand where 'nil' is coming from. Can someone help me with > this one? Thank you. > -- > Posted via http://www.ruby-forum.com/. > >

I’d rather do this like this

c = a.zip(b).map{ |a_ele, b_ele| a_ele * b_ele }

this will still give an error if b is shorter than a (but in Ruby1.9 a
will be cut IIRC).

HTH
Robert


http://ruby-smalltalk.blogspot.com/


As simple as possible, but not simpler.
Albert Einstein

thank you!

I will settle with this:

class MyArray
def count
a = [1,2,3]
b = [0.5,0.25]
num = a.length
i = 0
c = []
while i < num do
c << b.collect {|x| x * a[i]}
i += 1
end
puts c
end
end

number = MyArray.new
number.count

that way it does matter if I change the length of a.

thanks again.

Now, to make it a little more Ruby-y:

class MyArray
def count()
a = [1,2,3]
b = [0.5,0.25]
result = Array.new
a.each do |i|
result << b.collect {|x| x * i}
end
return result
end
end
number = MyArray.new
puts number.count

-Dana

On Wednesday 11 June 2008, Jason L. wrote:

  c << b.collect {|x| x * a[i]}

that way it does matter if I change the length of a.

thanks again.

You don’t need num. You can directly write:

while i < a.length

A much better alternative is:

a.each do |it|
c << b.collect{|x| x * it}
end

a.each passes each element of a, in turn, as argument to the block. Each
time
the block is called, it calls b.collect, multiplying the elements of b
for the
current element of a.

An even more elegant way to do this is to use inject (see ri
Enumerable#inject
for an explanation of how it works):

a = [1,2,3]
b = [0.5,0.25]
c = a.inject([]) do |res, i|
res << b.collect{|x| x*i}
end

Stefano

this is great! thanks so much.