【问题标题】:Sum entries in List3 with index from List1 when List1 == List2当 List1 == List2 时,将 List3 中的条目与 List1 中的索引相加
【发布时间】:2019-01-28 17:02:29
【问题描述】:

所以我试图在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])

【问题讨论】:

  • 是否有任何错误/意外行为?请具体。
  • 您能添加一个输入示例和预期输出吗?

标签: python list list-comprehension


【解决方案1】:

首先,在变量名上坚持使用 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]如果你有 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

时间复杂度是一样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2021-04-27
    • 2021-09-10
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多