Python:使用列表推导式过滤列表的更快方法

Python: Faster way to filter a list using list comprehension

考虑以下问题:我想保留 list1 中属于 list2 的元素。所以我可以这样做:

filtered_list = [w for w in list1 if w in list2]

我需要对 list1 的不同示例(大约 20000 个不同的示例)和 "constant"(冻结的)list2 重复相同的过程。

我怎样才能加快这个过程?

我还知道以下属性:

1) list1 有重复元素且未排序且大约有 10000(万)项。

2) list2 是一个巨大的排序列表(大约 200000 - 20 万)条目 Python) 并且每个元素都是唯一的。

我想到的第一件事是也许我可以使用一种二进制搜索。但是,在 Python 中有没有办法做到这一点?

此外,如果 filtered_list 的 list1 项目顺序相同,我不介意。所以,也许我可以只检查 list1 的未重复版本,并且在删除 list1 中不属于列表 2 的元素后,我可以 return 重复的项目。

在 Python 3 中有快速的方法吗?

list2 转换为 set:

# do once
set2 = set(list2)

# then every time
filtered_list = [w for w in list1 if w in set2]

x in list2是连续的; x in set2 使用与字典相同的机制,因此查找速度非常快。

如果 list1 没有重复项,则将两者都转换为集合并取集合交集是可行的方法:

filtered_set = set1 & set2

但是对于重复项,您无法像上面那样迭代 list1

(正如您所说,您甚至可以使用 set1 - set2 看到您应该删除的元素,但是您仍然会陷入循环以删除 - 应该没有任何区别在过滤 keepers 和过滤垃圾之间的性能上,你仍然需要迭代 list1,所以这并不能胜过上面的方法。)

编辑以回应评论:将 list1 转换为 Counter 可能(编辑:或不;需要测试!)加快速度 如果你能像那样正常使用它(即你从来没有列表,你总是只处理一个Counter)。但是,如果您每次执行上述操作时都必须将 list1 预处理为 counter1,那么这同样是失败的 - 创建一个 Counter 将再次涉及一个循环。