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

时间:2015-03-18 15:40:45

标签: python list for-loop

我试图提高脚本的效率,该脚本会记录列表,并计算另一个' 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

令人惊讶的是它使用套装效率更高。

再次感谢所有人。

2 个答案:

答案 0 :(得分:13)

使用设置,这样您就不必继续循环:

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

答案 1 :(得分:2)

您可以将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)