2017-09-25 338 views
-1

我有一个约3000个项目的列表。我们称之为listA。 另一个包含1,000,000项的列表。我们称之为listBPython:如何获取一个列表中的项目数量

我想检查listB中有多少项listA。例如获得像436这样的答案。

显而易见的方法是使用嵌套循环查找每个项目,但这很慢,特别是由于列表的大小。

什么是最快和/或Pythonic的方式来获得属于另一个列表的项目数量?

+0

执行列表有重复的值?订单(例如物品索引)是否重要? – pstatix

回答

7

设置为list_b。这将避免嵌套循环,并使包含检查O(1)。整个过程将是O(M+N)这应该是相当最佳:

set_b = set(list_b) 
count = sum(1 for a in list_a if a in set_b) 
# OR shorter, but maybe less intuitive 
count = sum(a in set_b for a in list_a) 
# where the bool expression is coerced to int {0; 1} for the summing 

如果你不希望(或必须)在list_a算重复的元素,你可以使用交集:

count = len(set(list_a) & set(list_b)) 
# OR 
count = len(set(list_a).intersection(list_b)) # avoids one conversion 

还应该注意的是,这些基于集合的操作仅适用于列表中的项目是可散列的(例如,不是列表本身)!

+0

您可以通过跳过'list_b'的转换并使用方法形式:'set(list_a).intersection(list_b)'来简化第二个版本。 –

+0

Thx,您是对的,添加了该选项。 – schwobaseggl

+0

谢谢,那个工作就像一个魅力,它真的很快:) – Aventinus

0

您可以遍历的listA的内容,并使用一台发电机,以产生价值更有效率:

def get_number_of_elements(s, a): 
    for i in s: 
     if i in a: 
      yield i 
print(len(list(get_number_of_elements(listA, listB)))) 
+0

如果'a'是一个列表,这并不解决嵌套循环的主要性能问题。 '我在''必须仍然遍历列表! 此外,生成器函数是相当错误的名称,因为它不返回元素的数量。 – schwobaseggl

+0

@schwobaseggl生成器函数将生成's'中出现在'a'中的所有元素。通过将铸造生成器函数传递给'len'函数来计算重复次数。 – Ajax1234

+0

我明白它在做什么;)但是a)它并不是解决OP想要解决的嵌套循环问题,b)'get_number_of_elements(...)'没有获得元素的数量,而是一个生成器说元素。 – schwobaseggl

2

另一种选择是使用set并找到交集:

len(set(listA).intersection(listB)) 
+1

大多数算法性能明智。在这种情况下,'listA'碰巧是最小的,但通常最小的迭代应该在'set()'中被调用来快速查找,而遍历则是更长的迭代。 – pstatix

相关问题