循环查找不在 python 列表中的项目的最有效方法

Most efficient way to loop finding items not in a list in python

我正在尝试提高脚本的效率,该脚本获取列表并计算有多少项目不在另一个 'master' 列表 (list_of_all_items) 中。

感觉可能有更有效的方法来执行此操作,也许通过某种方式组合查询?

purple_count, brown_count, blue_count = 0, 0, 0

for item in list_of_purple_items:
    if item not in list_of_all_items:
        purple_count += 1

for item in list_of_brown_items:
    if item not in list_of_all_items:
        brown_list += 1

for item in list_of_blue_items:
    if item not in list_of_all_items:
        blue_count += 1

编辑:

感谢您的帮助。我 运行 一个快速测试,看看使用大型测试用例的最佳方法是什么:

    my original: 30.21s
           sets: 00.02s
         filter: 30.01s
  sum generator: 31.08s

令人惊讶的是,它使用集合的效率要高得多。

再次感谢大家

您可以将 sum 与生成器表达式一起使用,并将您的列表转换为 set 以更有效地检查成员资格:

main_set=set(list_of_all_items)
sum(1 for i in set(list_of_purple_items) if i not in main_set)

使用,这样您就不必一直循环:

set_of_all_items = set(list_of_all_items)
purple_count = len(set(list_of_purple_items).difference(list_of_all_items))
brown_count = len(set(list_of_brown_items).difference(list_of_all_items))
blue_count = len(set(list_of_blue_items).difference(list_of_all_items))

这样效率要高得多,因为集合交集只需要对所涉及的两个集合之一进行循环;然后可以在恒定时间内针对另一组测试每个项目。循环是在 C 代码中完成的(在创建 set 对象和计算差异时)。

并不是真的需要对所有项目使用集合,因为 set.difference() 接受任何可迭代对象,但它稍微快一些:

>>> import timeit
>>> import random
>>> all = range(10000)
>>> random.shuffle(all)
>>> all[:-1000] = []
>>> some = [random.randrange(10000) for _ in range(1000)]
>>> timeit.timeit('len(set(some).difference(all))', 'from __main__ import some, all', number=10000)
0.9517788887023926
>>> timeit.timeit('len(set(some).difference(all))', 'from __main__ import some, all; all = set(all)', number=10000)
0.90407395362854