首先,在变量名上坚持使用 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]:如果你有 3 次 @987654343 @ 在list2 中,将list3[i] 添加到结果中的3 倍)。你可以使用collections.Counter:
>>> import collections
>>> c2 = collections.Counter(list2)
>>> sum(v3*c2[v1] for v1, v3 in zip(list1, list3))
计数器将list2 的每个元素映射到其出现次数:list2 中有c2[v1] 值v1。
时间复杂度是一样的。