Reputation: 51
so I'm pretty much a n00b at Ruby, and I've put together a code to solve a MinCut problem (for an assignment, yes - that part of the code I've put together and tested), and I can't figure out how to read a file and put it into an array of arrays. I have a text file to read, with columns of varying length as below
1 37 79 164
2 123 134
3 48 123 134 109
and I'd like to read it into a 2D array, where each line and columnn is split, with each line going into one array. So the resulting array for the above example would be :
[[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]]
My code to read the text file is below:
def read_array(file, count)
int_array = []
File.foreach(file) do |f|
counter = 0
while (l = f.gets and counter < count ) do
temp_array = []
temp_array << l.to_i.split(" ")
int_array << temp_array
counter = counter + 1
end
end
return int_array
end
Any help is greatly appreciated!
Also, if it helps, the error I'm currently getting is "block in read_array': private method 'gets' called for # "
I've tried a few things, and have gotten different error messages though...
Upvotes: 5
Views: 22772
Reputation: 23
array_line = []
if File.exist? 'test.txt'
File.foreach( 'test.txt' ) do |line|
array_line.push line
end
end
Upvotes: 1
Reputation: 13574
File.readlines('test.txt').map do |line|
line.split.map(&:to_i)
end
Explanation
readlines
reads the whole file and splits it by newlines. It looks like this:
["1 37 79 164\n", "2 123 134\n", "3 48 123 134 109"]
Now we iterate over the lines (using map
) and split each line into its number parts (split
)
[["1", "37", "79", "164"], ["2", "123", "134"], ["3", "48", "123", "134", "109"]]
The items are still strings, so the inner map
converts them to integers (to_i
).
[[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]]
Upvotes: 24
Reputation: 19238
The error in your code occurs because you are calling the method gets
on the object f
, which is a String
, not a File
as you would expected (check the documentation for IO#foreach
for more informations).
Instead of fixing your code I suggest you to rewrite it in a simpler and more Rubyish style, I'd write it like this:
def read_array(file_path)
File.foreach(file_path).with_object([]) do |line, result|
result << line.split.map(&:to_i)
end
end
Given this file.txt
:
1 37 79 164
2 123 134
3 48 123 134 109
It produce this output:
read_array('file.txt')
# => [[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]]
Upvotes: 2
Reputation: 58324
def read_array(file)
int_array = []
File.open(file, "r").each_line { |line| int_array << line.split(' ').map {|c| c.to_i} }
int_array
end
Upvotes: 0
Reputation: 46687
Ruby's got you covered with just a few lines:
tmp.txt
1 2 3
10 20 30 45
4 2
Ruby code
a = []
File.open('tmp.txt') do |f|
f.lines.each do |line|
a << line.split.map(&:to_i)
end
end
puts a.inspect
# => [[1, 2, 3], [10, 20, 30, 45], [4, 2]]
Upvotes: 11