2017-04-21 109 views
1

想象我有一堆文件红宝石 - 读numerated文件

a_1, a_2, ..., a_n 
b_1, b_2, ..., b_n 

和我的脚本需要按以下顺序来读取文件:

a_1, b_1, a_2, b_2, ..., a_n, b_n 

我知道如何阅读文件时,名称被指定。即File.open("a_1.txt", "r"),但我可以指定名称,让我有一个循环,也只是像

while i < n 
    File.open("a_i.txt", "r") 
    do sth 
end 
+0

你需要像'File.open( “一_#{I} .TXT”, “R”)'?而'i'会改变,文件名也会改变,你将能够在每次新的迭代中读取新文件。检查此片段 - https://repl.it/HTfV – marmeladze

+0

@marmeladze将打开'a_1.txt','a_2.txt','a_3.txt'等等,而OP希望'a_1.txt', b_1.txt','a_2.txt','b_2.txt',... – Stefan

回答

1

我会做这样的事情:

file_names = (1..5).to_a.product(%w[a b]).map { |(a, b)| "#{b}_#{a}.txt" } 

file_names.each do |file_name| 
    # File.open(file_name, 'r') 
end 

5必须使用n被替换。

或者你可能想使用嵌套的循环:

(1..5).each do |n| 
    %w[a b].each do |c| 
    # File.open("#{c}_#{n}.txt", 'r') 
    end 
end 
+0

文件可以有'n'号码,如果有一些文件丢失,它可能会导致错误,所以更好地提取可用文件并对其进行排序根据OP的要求 –

-1

你需要的代码是:

while i < n 
    File.open("a_#{i}.txt", "r") { |file| 
     do sth 
    } 
end 

在一个字符串,当你把 “#{expr}的” 里面,值expr将在运行时进行评估和填充。 例子:

>irb 
irb(main):001:0> i = 5 
=> 5 
irb(main):002:0> "a_#{i}" 
=> "a_5" 
1

如果你事先不知道到底是什么文件都去那里,你可能要排序的目录列表。

files = Dir["/path/to/files/*.txt"].sort_by{|f| [f[\d+].to_i, f]} 
#=> ["a_1.txt", "b_1.txt", "a_2.txt", "b_2.txt", ...] 

这个按照文件名中的数字排序,然后是名称本身。然后,您只需按阵列顺序打开它们。

+0

您可能应该按照数字和字母进行排序。 – Stefan

+0

@Stefan这是一个很好的观点。 'Dir'会按ascii值对它们排序,但我想不能保证sort_by会保留它。 –

+0

我已经在我的答案中复制了你的第一行;) –

0
> files = Dir["/path/to/files/*.txt"] 
#=> ["a_5", "b_2", "b_9", "b_1", "b_10", "b_3", "b_5", "b_8", "a_1", "a_3", "a_8", "a_6", "a_2", "a_7", "b_6", "b_7", "b_4", "a_10", "a_4", "a_9"] 
> files_in_order = files.group_by{|e| e.split("_").last.to_i}.sort.map{|v| v[1].sort}.flatten 
#=> ["a_1", "b_1", "a_2", "b_2", "a_3", "b_3", "a_4", "b_4", "a_5", "b_5", "a_6", "b_6", "a_7", "b_7", "a_8", "b_8", "a_9", "b_9", "a_10", "b_10"] 
+1

你的第二个答案只能按整数排序。 –

3

你可以得到这些文件的基本名称,拆分周围_和排序[number, letter]

# filenames = Dir.glob('input/*') 
filenames = ["input/a_6", "input/b_8", "input/b_7", "input/a_3", "input/a_4", "input/b_4", "input/b_9", "input/b_1", "input/b_11", "input/a_11", "input/b_3", "input/b_2", "input/a_1", "input/b_6", "input/b_12", "input/a_8", "input/a_2", "input/a_9", "input/a_5", "input/b_10", "input/a_7", "input/b_5", "input/a_10", "input/a_12"] 

filenames.sort_by! do |filename| 
    letter, number = File.basename(filename).split('_') 
    [number.to_i, letter] 
end 

p filenames 
# ["input/a_1", "input/b_1", "input/a_2", "input/b_2", "input/a_3", "input/b_3", "input/a_4", "input/b_4", "input/a_5", "input/b_5", "input/a_6", "input/b_6", "input/a_7", "input/b_7", "input/a_8", "input/b_8", "input/a_9", "input/b_9", "input/a_10", "input/b_10", "input/a_11", "input/b_11", "input/a_12", "input/b_12"] 

我通常喜欢把输入文件和脚本在不同的文件夹。

最后,由于"3".to_i"3.txt".to_i都返回3,此代码应该适用于任何扩展名(包括无扩展名)。

+0

请注意,OP的示例中有一个“.txt”扩展名。 –

+0

@MarkThomas:请注意,OP的例子中有一半是'.txt'扩展名:)。 Alors'“3.txt”.to_i'仍然是'3',所以这段代码应该适用于任何扩展名。 –

+0

'to_i'并不真正关心,但如果你想明确说明它:'File.basename(filename,'.txt')' – Stefan

0

只是出于好奇,没有明确的分类:

Dir["/path/to/files/*.txt"].chunk { |e| e.split("_").first } 
          .map(&:last) 
          .reduce(&:zip) 
          .flatten 
+0

它不排序数组,它删除了一些有效的文件名,并可能引入'nil's。什么是不喜欢? :) –

+0

@EricDuminil我不知道我为什么删除了任何东西,但我相信,排序是由'Dir#[]'隐式完成的。 – mudasobwa

+0

'%w(a_1 a_2 b_1 b_2 b_3)' –