加快python列表操作的方法

Ray*_* P. 3 python multiprocessing

我有一个小的python程序,它逐行浏览一个大文本文件(5Mil +行),如果满足条件,则从每行中提取单个单词,然后将该单词附加到列表中(如果它尚未存在).之后我有一个巨大的列表,我需要按字母顺序排序,然后将列表中的项目写入新的文本文件.

代码如下所示:

big_list = []
with open('big_text_file.txt', 'r', encoding='UTF8') as f:
    for line in  f:
        # some validation specific to line structure:
        if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0) and '\t' in line:
            word = line.rsplit('\t')[0].lower()
            if word not in big_list:
                big_list.append(word)
sorted_list = sorted(big_list)
with open('results_file.txt', 'w', encoding='UTF8') as r:
    for item in sorted_list:
        r.write(item + "\n")
Run Code Online (Sandbox Code Playgroud)

问题是它很慢.有500万行,现在已经运行了12个多小时(!),还远未完成.我一定做错了什么.我有一个8核CPU,但在这种情况下只使用一个.CPU负载仅为12%.我可以应用多处理来加快速度吗?或者由于此代码的简单性,它没有多大用处?我仍然需要针对一个列表验证所有单词.

任何建议将不胜感激.

Jea*_*bre 5

正如评论中提到的,这里的主要瓶颈是使用a list.

旁白:if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)很慢,不起作用:line[0]是一个字符,而不是整数.使用isdigit()了点.

声明big_listset(),您可以替换:

if word not in big_list:
    big_list.append(word)
Run Code Online (Sandbox Code Playgroud)

只是

big_list.add(word)
Run Code Online (Sandbox Code Playgroud)

(word仅在尚未添加时才会添加set,并且与O(n)a 相比检查非常快,list因为它使用散列)

更好:您可以在一行中使用集合理解来重写代码(第一部分,甚至是排序部分):

with open('big_text_file.txt', 'r', encoding='UTF8') as f:
    big_list = sorted({line[:line.find('\t')].lower() for line in f if not line[0].isdigit() and '\t' in line})
Run Code Online (Sandbox Code Playgroud)

注意更好的方法来获取行的第一部分,避免分裂(并生成一个你几乎不使用的列表)

正如上面所说的,不需要测试inset:如果这个词已经在它,它不会被再次插入,并插入决定试验的目的是要快.

请注意,多处理可能有所帮助,但是你会遇到磁盘I/O瓶颈并且算法会更复杂,因为你必须通过跳过8个相等的行号来"拆分"你的大文件,创建集合并交叉它们......让我们坚持单一处理部分,看看它是如何发展的.

  • 甚至`line [0:line.find('\ t')]`而不是`line.rsplit('\ t')[0] (2认同)