2016-08-23 54 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