Howzlife17
Howzlife17

Reputation: 51

How do I read a text file into an array of array (each sub-array being a row in the text file?)

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

Answers (5)

Reza
Reza

Reputation: 23

array_line = []  

if File.exist? 'test.txt'
  File.foreach( 'test.txt' ) do |line|
      array_line.push line
  end
end

Upvotes: 1

tessi
tessi

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

toro2k
toro2k

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

lurker
lurker

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

Chowlett
Chowlett

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

Related Questions