我有一个巨大的列表,它是all_entries
(目前是80k整数项)。在此列表中包含我已在整个程序中处理的项目。
当我的程序使用以下方法时,通常需要大约30秒才能到达return语句。我怎样才能加快速度呢?
提示:new_entries
长40公斤,也是如此之大。
def get_fresh_entries(self, new_entries, all_entries):
"""
:param new_entries: Entries from which some might already be in all_entries.
:param all_entries: Entries already handled and saved.
"""
fresh = []
shuffle(new_entries)
for i in new_entries:
if i not in all_entries:
fresh.append(i)
if len(fresh) > 80000:
break
return fresh
答案 0 :(得分:3)
唯一问题是为每个新条目执行的行if i not in all_entries:
,并针对最多80,000个现有条目进行测试。
重要的是要理解在列表或集合上执行测试时的区别。
因此,只需将all_entries
转换为一次设置(!)即可消除主要速度问题。
...
all_entries_set = set(all_entries)
for i in new_entries:
if i not in all_entries_set:
...
虽然还有其他提示如何使用集合加速程序是至关重要的,因为它会降低复杂性。
答案 1 :(得分:2)
列表理解将会:
作为 @Delgan 评论,如果all_entries是一个集合,则更好。
all_entries = set(all_entries)
然后:
fresh = [x for x in new_entries if x not in all_entries]
另请查看itertools.ifilter,它是lazyly evaluated:
fresh = itertools.ifilter(lambda x: x not in all_entries, new_entries)
如果你只需要保留第一个n
数据,因为itertools很懒,你可以像这样:
fresh = itertools.islice(itertools.ifilter(lambda x: x not in all_entries,
new_entries),
n))
或与列表理解相似,但改为使用生成器:
fresh = itertools.islice((x for x in new_entries if x not in all_entries), n)