Reputation: 29
I'm attempting to write a function that uses array methods to do a variety of things. I need to use the each method to print the cube of each element in the array. Here's my code.
def foo(a)
a.each { |x| puts x ** 3 }
a.each_slice(3) { |x| puts x }
a.select do |x|
if x%5 == 0
puts x
end
end
a.map { |x| x ** 3 }
aa.inject(0) { |x, y| x * y }
end
a = Array.new(50)
a.each { |x| x = rand(10..100) }
foo(a)
I keep getting this error:
Traceback (most recent call last):
3: from task2.rb:21:in `<main>'
2: from task2.rb:3:in `foo'
1: from task2.rb:3:in `each'
task2.rb:3:in `block in foo': undefined method `**' for nil:NilClass (NoMethodError)
Upvotes: 1
Views: 126
Reputation: 4440
#each
is just a simple iteration, it's doesn't modify the array.
Instead of:
a = Array.new(50)
a.each { |x| x = rand(10..100) }
you can simply do this:
a = Array.new(50) { rand(10..100) }
Upvotes: 2
Reputation: 87516
You should use the Ruby p
method to help you debug things. (p x
is a shortcut puts x.inspect
.)
So try running the following program:
a = Array.new(50)
a.each { |x| x = rand(10..100) }
p a
From the output of that program, you can see that your array just consists of 50 nils. So then your real question is: How do I initialize an array properly? The x
argument to your block is not some kind of reference to a cell in the array, it is simply a copy of the value that was held in the array, so writing to x
does not do anything to the array.
The simplest way that would work for your application is:
a = Array.new(50) { rand(10..100) }
You could also write it like this:
a = 50.times.map { rand(10..100) }
You could also initialize your array in a more manual way by appending to it 50 times:
a = []
50.times { a << rand(10..100) }
You could also use the []=
method, which is the most general way to write to an array:
a = []
50.times { |i| a[i] = rand(10..100) }
It's worthwhile to know about each of these different ways to make an array.
Upvotes: 0
Reputation: 11226
You're not modifying your array of 50 nil values. Try map!
instead.
a.map! { |x| x = rand(10..100) }
Not sure exactly what the rest of your code is supposed to do but this seems more likely it.
def foo(a)
a.each { |x| puts x ** 3 }
a.each_slice(3) { |x| puts x }
a.each do |x| # not sure why you wanted select, does not make sense here
if x % 5 == 0
puts x
end
end
a.map { |x| x ** 3 }
.inject(0) { |x, y| x * y }
end
array = Array.new(50)
array.map! { |x| x = rand(10..100) }
foo(array)
Upvotes: 0
Reputation: 3285
This line:
a.each { |x| x = rand(10..100) }
doesn't do what you think it does. Each does not alter the original array. If you want to change the original values of a you need a map!.
irb(main):025:0> a = Array.new(50)
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
irb(main):026:0> a.each { |x| x = rand(10..100) }
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
irb(main):027:0> a
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
irb(main):028:0> a.map { |x| x = rand(10..100) }
=> [67, 34, 96, 50, 52, 68, 14, 88, 67, 19, 83, 40, 35, 98, 88, 98, 39, 73, 41, 60, 25, 47, 33, 73, 20, 41, 32, 19, 65, 67, 47, 14, 11, 67, 32, 32, 13, 36, 23, 100, 14, 10, 73, 20, 59, 94, 54, 25, 57, 28]
irb(main):029:0>
a
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
a.map! { |x| x = rand(10..100) }
=> [97, 83, 52, 54, 22, 54, 39, 32, 42, 70, 84, 15, 69, 32, 28, 40, 50, 98, 66, 79, 25, 37, 97, 28, 30, 11, 98, 57, 73, 77, 99, 75, 72, 40, 67, 62, 87, 41, 58, 10, 88, 24, 98, 10, 31, 94, 53, 43, 98, 17]
irb(main):032:0> a
=> [97, 83, 52, 54, 22, 54, 39, 32, 42, 70, 84, 15, 69, 32, 28, 40, 50, 98, 66, 79, 25, 37, 97, 28, 30, 11, 98, 57, 73, 77, 99, 75, 72, 40, 67, 62, 87, 41, 58, 10, 88, 24, 98, 10, 31, 94, 53, 43, 98, 17]
irb(main):033:0>
Also the preferred way to do this is with a range IMO.
Upvotes: 2