2016-08-23 68 views
3

我有~5M csv文件存儲在〜100.000文件夾中。每個文件夾包含大致相同數量的文件,並且文件夾中始終有偶數個文件。我需要找到所有這些文件的路徑,並將它們加載到一個統計建模項目的奇怪順序列表中。在大目錄中查找隨機對

特別是,我需要以下要堅持:

  • 唯一性:每個文件只能在列表中一次
  • 對:每個文件必須是同一文件夾旁邊的另一個文件(它可以是兩個,如果由於隨機性)
  • 隨機性:任何兩個文件不是「配對」彼此相鄰的概率應該是相同的(即它不會工作只是爲了迭代所有文件)

我在下面創建了一個示例。

文件

Folder_1 
- File_A 
- File_B 
- File_C 
- File_D 
Folder_2 
- File_E 
- File_F 
- File_G 
- File_H 

良好的結果(隨機的,但堅持對的規則)

paths = ['Folder_1/File_A', 'Folder_1/File_D', 'Folder_2/File_G', 'Folder_2/File_F', 'Folder_2/File_E', 'Folder_2/File_H', 'Folder_1/File_C', 'Folder_1/File_B'] 

一個簡單的方法可能是這樣的「隨機選擇一個文件夾,挑該文件夾中的隨機文件和該文件夾中的一對隨機文件,將這些文件保存在列表中以避免再次被選中,重複。「但是,這將花費太長時間。你能推薦一個創建這個列表的好策略嗎?如果需要,隨機性要求可以放鬆一點。

+0

你有什麼企圖? – depperm

+0

是的,我已經完成了我在底部描述的簡單方法的粗略版本。 – pir

+0

文件/文件夾名稱是否遵循某種模式? – Bahrom

回答

1

確保所有東西都是隨機的一種方法是使用random.shuffle,這將隨機播放列表。這樣,您可以簡單地將每個項目與其鄰居配對,在知道配對是隨機的情況下是安全的。爲了獲得像你的例子一樣的結果,你可以隨機洗牌並將結果列表對齊。這裏有一個例子:

from random import shuffle 

# generate some sample directory names 
ls = [[]] * 5 
i = 0 
while i < len(ls): 
    ls[i] = [str(i) + chr(j) for j in range(97,101)] 
    i += 1 

# shuffle files within each directory 
pairs = [] 
for l in ls: 
    shuffle(l) 
    pairs += list(zip(l[1::2], l[::2])) 

# shuffle and flatten the list of pairs 
shuffle(pairs) 
flat = [item for sublist in pairs for item in sublist]  
print(flat) 
+0

謝謝 - 這個工程!我有一個非常相關的任務,我需要找到這樣的列表,但每對必須包含不同文件夾中的文件。其他要求仍然適用。你有關於如何修改這個相關任務的解決方案的建議嗎? – pir

+0

當然!我只是將最初的清單弄平,然後再打亂清單。既然你有100,000個文件夾,每個來自同一個文件夾的兩個文件對的機率很小,所以儘管它不能保證它應該工作得很好。 – dpercy

+0

是的,我也在考慮它。也許我應該忽略錯誤的小機會:)謝謝。 – pir

1

最好的策略是分割和征服一些線程的幫助。您希望儘可能快地將文件名加載到內存中,以便最快完成。

第一步是爲每個文件夾中的文件夾列表創建一個文件夾名稱的隊列,另一個隊列。例如:

folders = queue.Queue() 
files = queue.Queue() 

一個隊列很像一個列表,只有它可以在不同線程之間安全共享。一次使用線程處理多個文件夾會加快處理時間。

創建一個函數,該函數將獲取每個文件夾的路徑,然後存儲每個路徑「文件夾」隊列。

folderPaths = getFolderPaths() 
for path in folderPaths: 
    folders.put(path) 

最終,你將結束與它的所有文件夾路徑隊列(如[「文件夾A」,「文件夾B」,...])

做了一名工人功能線程將遍歷文件夾中的所有文件並將每個文件的名稱存儲在列表中。總體思路是:

def threadJob(): 
    while True: 
     folderPath = folders.get() 
     if folderPath is None: 
      break 
     fileNames = getFilesInFolder(folderPath) 
     files.put(fileNames) 

這裏「getFilesInFolder()」是一個函數,在路徑參數,並返回該文件夾中的所有文件的列表。

當所有線程完成時,「文件」應該充滿每個文件夾的文件列表。現在您需要將隊列清空爲常規列表。

fileList = [] 
file = files.get() 
while file not None: 
    fileList.append(file) 
    file = files.get() 

現在您有一份列表。洗牌每個列表來隨機文件順序:

for files in fileList: 
    random.shuffle(files) 

現在你可以創建最終名單(statList)和彈出,對從隨機選擇的子列表中的文件,直到所有的文件已經附加:

statList = [] 

while len(finalFileList > 0): 
    index = random.randrange(len(fileList)) 
    if len(fileList[index]) == 0: 
     fileList.pop(index) 
    else: 
     statList.append(fileList.pop()) 
     statList.append(fileList.pop()) 

不保證這會很快,但它是我能想到的最快速的方法。約隊列

更多信息和線程如果有興趣:

https://docs.python.org/3/library/queue.html

http://www.tutorialspoint.com/python3/python_multithreading.htm