如何将文本文件读入一个数组的数组中(每个子数组都是文本文件中的一行)?

5

我对Ruby编程非常陌生,但已编写了一段代码来解决最小割问题(是一个作业,我已经编写并测试了这部分代码),但我无法弄清如何读取文件并将其放入数组中。 我有一个文本文件要读取,其中包含不同长度的列,如下所示:

1 37 79 164

2 123 134

3 48 123 134 109

我想将其读入一个二维数组中,其中每行和每列都被拆分,每行进入一个数组。 因此,上面示例的结果数组将为:

[[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]]

我用来读取文本文件的代码如下:

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

非常感谢您的帮助!

如果有帮助的话,我目前遇到的错误是"block in read_array': private method 'gets' called for # "

我尝试了一些方法,但得到了不同的错误消息...

5个回答

24
File.readlines('test.txt').map do |line|
  line.split.map(&:to_i)
end

解释

readlines 函数读取整个文件并按照换行符分割。它的使用方式如下:

["1 37 79 164\n", "2 123 134\n", "3 48 123 134 109"]
现在,我们使用map迭代每一行,并将每一行分割成数字部分(split)。
[["1", "37", "79", "164"], ["2", "123", "134"], ["3", "48", "123", "134", "109"]]

这些项目仍然是字符串,因此内部的 map 将它们转换为整数(to_i)。

[[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]]

&:是什么意思? - winklerrr
1
.map(&:to_i) 相当于 .map { |s| s.to_i }。更具体地说,& 调用符号上的 to_proc 方法。参见:http://ruby-doc.org/core-2.3.1/Symbol.html#method-i-to_proc - tessi

11

只需要几行代码,Ruby 就可以帮你搞定:

tmp.txt

1 2 3
10 20 30 45
4 2

Ruby 代码

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

非常感谢!这就是我喜欢 Ruby 的原因,每当我遇到问题时,答案往往比我之前想象的要简单得多。 - Howzlife17

2
你代码中的错误是因为你在字符串对象 f 上调用了方法 gets,而不是像你期望的那样调用 File 对象(请查看IO#foreach文档以获取更多信息)。
我建议你不要修复你的代码,而是用更简单、更具Ruby风格的方式重写它。我会这样写:
def read_array(file_path)
  File.foreach(file_path).with_object([]) do |line, result|
    result << line.split.map(&:to_i)
  end
end

假设有这个file.txt文件:

1 37 79 164
2 123 134
3 48 123 134 109

它会生成以下输出:
read_array('file.txt')
# => [[1, 37, 79, 164], [2, 123, 134], [3, 48, 123, 134, 109]] 

+1,因为他解释了他得到的错误。我们其他人都忘记了 :) - tessi

1
array_line = []  

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

1
虽然这段代码可能回答了问题,但提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - Benjamin W.

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接