5

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...

5 Answers 5

24
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]]
Sign up to request clarification or add additional context in comments.

2 Comments

What is the &: for?
.map(&:to_i) is equivalent to .map { |s| s.to_i }. More specifically, the & calls to_proc on the symbol. See: ruby-doc.org/core-2.3.1/Symbol.html#method-i-to_proc
11

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]]

1 Comment

Thank you so much! That's why I'm loving ruby, every time I'm having trouble with something the answer turns out to be much easier than previously thought
2

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]] 

1 Comment

+1 for explaining the error he got. The rest of us forgot that :)
1
array_line = []  

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

1 Comment

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
0
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.