当List1 == List2时,List3中的条目总和List1中的索引

时间:2019-01-28 17:02:29

标签: python list list-comprehension

因此,我尝试根据List1 == List2时来自List1的索引来从List3中求和。我很确定问题出在声明开头的List3[y],但我不知道该放什么。

这种理解是要替换也发布的嵌套for循环(按预期工作)。

谢谢。

#This loop works as intended, but takes a long time
for y in range(len(List1)):
    for x in range(len(List2)):
        if List1[y] == List2[x]:
            sumValue += List3[y]   


#Trying to build using this list comprehension sum
sumValue = sum([List3[y] for y, val1 in enumerate(List1) for x, val2 in enumerate(List2) if val1==val2])

1 个答案:

答案 0 :(得分:0)

首先,在变量名上坚持使用PEP8:list1而不是List1

第二,我认为您的列表理解是可以的,但是您可以简化它。

注意:我假设是len(list1) == len(list3)

如果list2的元素是唯一的

您想知道val1中是否有list2。有in运算符可以实现以下目的:

sum([list3[i] for i, v in enumerate(list1) if v in list2])

在列表中查找值的时间复杂度为O(n),但是如果将列表转换为集合,则复杂度为O(1):

set2 = set(list2)
sum([list3[i] for i, v in enumerate(list1) if v in set2])

将会更快

最后,您可以删除括号,因为sum接受生成器:

set2 = set(list2)
sum(list3[i] for i, v in enumerate(list1) if v in set2)

这是一个简单的基准:

>>> list1=[random.randint(0,10000) for _ in range(10000)]
>>> list2=[random.randint(0,10000) for _ in range(10000)]
>>> list3=[random.randint(0,10000) for _ in range(10000)]
>>> timeit.timeit(lambda: sum(list3[i] for i, v in enumerate(list1) if v in list2), number=100)
61.139454132004175
>>> set2 = set(list2)
>>> timeit.timeit(lambda: sum(list3[i] for i, v in enumerate(list1) if v in set2), number=100)
0.09698906799894758

如果要删除索引,可以使用zip

sum(v3 for v1, v3 in zip(list1, list3) if v1 in set2)

此版本似乎比上一个版本快一点:

>>> timeit.timeit(lambda: sum(v3 for v1, v3 in zip(list1, list3) if v1 in set2), number=100)
0.07421852700645104

如果list2的元素不是唯一的

您想知道多少次 val1list2中。 (这就是您的代码的工作:对于list1[i]的每个元素list3[i],为list2的每个元素添加list[i] 如果您在list1[i]中有3次list2,请在结果中添加3次list3[i] )。您可以使用collections.Counter

>>> import collections
>>> c2 = collections.Counter(list2)
>>> sum(v3*c2[v1] for v1, v3 in zip(list1, list3))

计数器将list2的每个元素映射到它的出现次数:c2[v1]中有v1个值list2

时间复杂度相同。