因此,我尝试根据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])
答案 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
的元素不是唯一的您想知道多少次 val1
在list2
中。 (这就是您的代码的工作:对于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
。
时间复杂度相同。