Reputation: 9
out_file = File.open "out_file.txt" , 'w' do |f|
matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
f.puts "matrix test"
f.puts " int at [0,2]: #{matrix[0][2]}"
f.puts " int at [2,0]: #{matrix[2][0]}"
f.puts " int at {1,1]: #{matrix[1][1]}"
above code produces this:
"matrix test
int at [0,2]: 3
int at [2,0]: 7
int at {1,1]: 5"
but this code using the same matrix variable declaration ..
rows = Array(0..3)
cols = Array(0..3)
rows.each do |r|
cols.each do |c|
f.puts "row:#{r} col:#{c} = #{matrix[r][c]},"
end
end
produces an error:
undefined method `[]' for nil:NilClass (NoMethodError)
Can anybody please tell me what's going on?
Upvotes: 0
Views: 97
Reputation: 19221
The previous answers are right, but I thought I would raise the issue of the approach...
Why are you creating ranged arrays instead of using the actual length of the matrix arrays in question...?
Maybe something like this would remove the need to assume the matrix's composition:
out_file = File.open "out_file.txt" , 'w' do |f|
matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
f.puts "matrix test"
matrix.length.times do |r|
matrix[r].length.times do |c|
f.puts "row:#{r} col:#{c} = #{matrix[r][c]},"
end
end
Upvotes: 0
Reputation: 967
As Tony suggests, using rows=Array(0..2) or rows=Array(0...3) will work for you.
You can also use the range directly and forgo the array creation, like this:
rows = 0...3
cols = 0...3
...
Upvotes: 1
Reputation: 1239
There are 2 types of ranges, the inclusive ..
and the exclusive ...
which doesn't include the right most digit.
A range such as 0..5
will have every number including the 5. (ie. 0,1,2,3,4,5)
A range such as '0...5' will have every number excluding the 5. (ie. 0,1,2,3,4).
So if you notice your error message,
undefined method `[]' for nil:NilClass (NoMethodError)
You need to begin to wonder what could be running a method on nil
. Well, you have this matrix declaration of:
matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
So that when this range pops up that is expressed as:
rows = Array(0..3)
It will go through 0,1,2, and also 3. Well, there is no 3
index in that array since your array begins counting at 0 and ends at 2. So when the 3
index hits, the value of it is beyond anything you've declared - it's nil
. When you try to run that method on it (to call the spot in the array you want), the error message tells you that you can't run a method (which the []
is actually) on nil
.
Paying close attention to your error messages, as well as understanding the 2 types of ranges should help you catch these sorts of errors in the future as well. Leave a comment if this doesn't make total sense.
Upvotes: 0
Reputation: 2378
The problem is your Array(0..3)
, it is generating an array [0,1,2,3]
instead of what you want: [0,1,2]
.
You actually want to use ...
: Array(0...3) => [0,1,2]
.
Or you could just change the range inside to 0..2
: Array(0..2) => [0,1,2]
Check out the documentation for Range for more information.
Upvotes: 1