加快python列表操作的方法

时间:2017-05-05 11:29:03

标签: 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")

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

非常感谢任何建议。

1 个答案:

答案 0 :(得分:5)

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

除此之外:if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)速度慢且不起作用:line[0] char ,而不是整数。请使用isdigit()

big_list声明为set(),您可以替换:

if word not in big_list:
    big_list.append(word)

只是

big_list.add(word)

(仅当word中尚未添加set时才会添加,O(n)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})

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

如上所述,无需为in测试set:如果该单词已经在其中,则不会再次插入,并且插入决策的测试设计为快速

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