Ruby:从文件中读取整数并将它们放入数组中

3
我有一个文件(InputFile.txt),其中包含使用*字符分隔的整数块。每个块包含一些行,每行包含三个整数,例如:

4 1233 8

2 55 11

2 4 33

*

3 5 34

2 1 44

6 5 33

*

我想读取每个块并将每个块中的整数放入2D数组中,并对其进行一些处理。我找到了以下代码:
f = File.read 'InputFile.txt'
f.split('*').each  do |set|
  set.split.map(&:to_i)

这段代码可以读取每个块,但我不知道如何将每个块放入2D数组中。例如,我尝试了set[0][0],它返回4,但当我尝试set [0] [1]时,它返回空格。有人能告诉我该怎么做吗?我希望看到第二个数字是1233

4个回答

3
f = File.read 'InputFile.txt'
data_array = f.split('*').map  do |block|    
    block.split(/\n+/)
    .map { |e| e.split(/\s+/)
    .map(&:to_i) }
    .reject { |a| a.empty? }
end
# => [[[4, 1233, 8], [2, 55, 11], [2, 4, 33]], 
#     [[3, 5, 34], [2, 1, 44], [6, 5, 33]]]

这将适用于由*分隔的任意数量的。在每个块中,由任意数量的换行符分隔,在每一行中,整数元素由任意数量的空格分隔。
由于每个块都是一个图形,每个中的三个元素分别表示源节点目标节点权重,所以要访问这些信息,可以执行以下操作:
data_array.each_with_index do |row, index|
    p "Graph: #{index}"
    row.each do |inner_row|
        p "source_node: #{inner_row[0]}, dest_node: #{inner_row[1]}, weight: #{inner_row[2]}"
    end
    p '- - -'
end

# => "Graph: 0"
# "source_node: 4, dest_node: 1233, weight: 8"
# "source_node: 2, dest_node: 55, weight: 11"
# "source_node: 2, dest_node: 4, weight: 33"
# "- - -"
# "Graph: 1"
# "source_node: 3, dest_node: 5, weight: 34"
# "source_node: 2, dest_node: 1, weight: 44"
# "source_node: 6, dest_node: 5, weight: 33"

谢谢,我该如何访问每个数字?例如使用block[0][0]? - starrr
你可以循环遍历数组并打印数字。请问您想要用这个做什么? - K M Rakibul Islam
我想将每个块用作图形,其中第一个数字是第一个节点,第二个数字是第二个节点,第三个数字是连接两个节点的边的权重,因此我需要访问每个组件。 - starrr
@starrr请查看我的更新答案,如果您有任何其他问题,请告诉我。 - K M Rakibul Islam
1
完美!非常感谢 :) - starrr
1
非常欢迎。很高兴能帮到你。祝你好运 :) - K M Rakibul Islam

2

如果文件不是太大,您可以将其“gulp”到字符串中,在星号上拆分(以及每侧的空格),然后分解这些片段。

首先让我们将一些数据写入文件:

str =<<-BITTER_END
4 1233 8
2 55 11

2 4 33
*
3 5 34

2 1 44
6 5 33
*
5 4 1
22 65 98
13 15 71
BITTER_END


FName = 'temp'
IO.write(FName, str) #=> 75

现在我们来读取和处理文件:

 IO.read(FName).
   split('*').
   map { |s| s.strip.split(/\n+/).map { |s| s.strip.split.map(&:to_i) } }
  #=> [[[4, 1233, 8], [2, 55, 11], [2, 4, 33]],
  #    [[3, 5, 34], [2, 1, 44], [6, 5, 33]],
  #    [[5, 4, 1], [22, 65, 98], [13, 15, 71]]] 

这是另一种写法。它更加冗长,但可以自我记录,方便调试和测试,并提高可维护性:

class String
  def to_blocks(split_char)
    split(split_char)
  end

  def to_lines
    strip.split(/\n+/)
  end

  def to_arr_of_ints
    strip.split.map(&:to_i)
  end
end

然后:

IO.read(FName).to_blocks('*').map { |block|
  block.to_lines.map { |line|
    line.to_arr_of_ints } }
  #=> [[[4, 1233, 8], [2, 55, 11], [2, 4, 33]],
  #    [[3, 5, 34], [2, 1, 44], [6, 5, 33]],
  #    [[5, 4, 1], [22, 65, 98], [13, 15, 71]]] 

如果您不想使用猴子补丁来修改String,可以使用Refinements或者只需将这三种方法的其中一个参数设置为字符串。


1
f.split("*").each do |block|
    result.push []

    block.split("\n").each do |line|
        result[-1].push line.split.map{ |i| i.to_i } unless line.split.size == 0
    end
end

每个块都应该是一个整数数组的数组,而不是一个整数数组。 - Cary Swoveland

1

修改了您的代码以添加嵌套数组:

output = []

col = 0
row = 0

f = File.read 'InputFile.txt'
f.split('*').each do|set|
    output[row] = []
    set.split(' ').each do|item|
        output[row][col] = item
        col += 1
    end
    row +=1
    col = 0
end
print output

结果:

[["4", "1233", "8", "2", "55", "11", "2", "4", "33"], ["3", "5", "34", "2", "1", "44", "6", "5", "33"]]

请确保末尾没有*,否则会创建空的内部数组。另外不确定您是否希望将每个新行的数字放在自己的数组中,还是读取到下一个星号为止。我假设读取到星号。


每个块应该是一个整数数组的数组,而不是整数数组。 - Cary Swoveland
OP说星号定义了块,因此每个星号都是主数组中的子数组。 - the happy mamba
是的,但OP说:“...将每个块中的整数放入2D数组中...”。顺便说一句,当您回复评论时,应包括成员的名称(例如@Cary),以便SO通知成员留下了消息。 - Cary Swoveland
@CarySwoveland 我们会等待原帖发布更多细节 :) - the happy mamba

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