我有~~ 500万个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']
一个简单的方法可能是"选择一个随机文件夹,在该文件夹中选择一个随机文件,并在文件夹中选择一个随机对。将这些选择保存在列表中以避免再次被选中。重复。&#34 ;.但是,这需要太长时间。你能推荐一个很好的策略来创建这个列表吗?如果需要,可以稍微放宽随机性要求。
答案 0 :(得分: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)
答案 1 :(得分:1)
最好的策略是在线程的帮助下分而治之。您希望尽快将文件名加载到内存中以便最快完成。
第一步是为文件夹名称创建一个队列,为每个文件夹中的文件列表创建另一个队列。类似的东西:
folders = queue.Queue()
files = queue.Queue()
队列很像列表,只能在不同线程之间安全共享。使用线程一次处理多个文件夹将加快处理时间。
创建一个函数,它将获取每个文件夹的路径,然后存储每个路径“folders”队列。
folderPaths = getFolderPaths()
for path in folderPaths:
folders.put(path)
最终你会得到一个包含所有文件夹路径的队列(例如[“文件夹A”,“文件夹B”,...])
为将遍历文件夹中所有文件的线程创建一个worker函数,并将每个文件的名称存储在列表中。一般的想法是:
def threadJob():
while True:
folderPath = folders.get()
if folderPath is None:
break
fileNames = getFilesInFolder(folderPath)
files.put(fileNames)
这里“getFilesInFolder()”是一个函数,它接受一个path参数并返回该文件夹中所有文件的列表。
当所有线程都完成时,“files”应该包含每个文件夹的文件列表。现在,您需要将队列清空为常规列表。
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