2017-04-21 114 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)' –