【问题标题】:Increase variable in comprehension with if statement?使用 if 语句增加理解变量?
【发布时间】:2018-05-11 16:27:55
【问题描述】:

我正在尝试学习 Python 理解,但我被困住了。当条件为True 时,我试图增加我的count 变量,而return 在循环后计数。这是我的代码:

list = [1,2,4,5,7,8,10]
d = 3
count = 0
return [count for x in range(len(list))
        if list[x] + d in list and list[x] + 2 * d in list]

每次我的条件为True 时,它都会返回"0"。当我尝试在理解中添加count += 1 时,它给了我一个SyntaxError

【问题讨论】:

  • 明确地说,您正在尝试编写一个单行代码来计算列表中e + 3e + 6 的元素数量?
  • @MadPhysicist 是的,没错
  • 列表推导只能包含 表达式count = count + 1 是一个赋值(statement),所以你不能在那里使用它。
  • @MatiasCicero 感谢您的说明!

标签: python python-3.x list list-comprehension


【解决方案1】:

Comprehensions 不能这样工作。从概念上讲,它们允许您设置和过滤列表的各个元素,而不是累积到单个变量中。

不过,有一个标准的习语可以解决这个问题。您基本上可以为您的条件制作一个可迭代的布尔值,或者只为您想要的所有元素保留一个并丢弃其他元素,然后sum 结束。

作为进一步的改进,我建议使用generator expression 而不是列表推导式。它看起来几乎一样,但支持惰性求值。这意味着您可以获得单线的所有好处,而无需将标志值列表存储在内存中。

这是第一个选项的外观:

L = [1,2,4,5,7,8,10]
count = sum((x + d in L and x + 2 * d in L) for x in L)

第二个选项如下所示:

L = [1,2,4,5,7,8,10]
count = sum(1 for x in L if (x + d in L and x + 2 * d in L))    

请注意,我将您的变量 list 重命名为 L,这样它就不会影响内置函数。

【讨论】:

  • 感谢您的解释和示例代码!对我很有帮助
【解决方案2】:

不要?

for x in lst:
    if x+d in lst and x+2*d in lst:
        count += 1

或者使用 len:

count = len([_ for x in lst if x+d in lst and x+2*d in lst])

或使用总和:

count = sum(1 for x in lst if x+d in lst and x+2*d in lst)

或使用集合(准备好感到惊讶):

count = len(({x + d for x in lst} | {x + 2 * d for x in lst}) & set(lst))

这是 1000 个连续数字列表中的性能数字:

loop:    20.3 ms ± 8 ms
len:     25.4 ms ± 8.22 ms
sum:     18.3 ms ± 5.06 ms
sets:    272 µs ± 19 µs  (~100x faster)

这不是性能的保证。在这种情况下,集合也可能是内存效率最低的解决方案。但它确实有效(看起来很不错)。

另外,不要将变量命名为 list,这是 Python 中的内置函数,覆盖它会导致各种混乱。

【讨论】:

  • 虽然涵盖了其他答案中的大部分内容,但时间位很好。 +1
【解决方案3】:

你很亲密。列表推导式不能以您希望的方式存储和重用变量;它们可能只包含表达式。一种解决方案是将sum 与生成器表达式一起使用。

此解决方案的好处是您避免了构建列表的费用,而无需计算满足条件的元素数量。

A = [1,2,4,5,7,8,10]
A_set = set(A)

d = 3
count = 0

res = sum(1 for x in range(len(A)) if \
          (A[x]+d in A_set) and (A[x]+2*d in A_set))

# 3

注意你不应该在类之后命名变量。此外,您可以使用set 进行 O(1) 查找。

还请注意,我们在列表推导之外构造A_set,否则将为range(len(A)) 的每次迭代计算它。

【讨论】:

  • 很高兴使用set。 +1
  • 虽然不需要遍历范围。只需直接遍历A
  • 在理解之外计算 A_set 非常重要 - 由于重复重建集合的成本,内联 set(A) 将抵消任何好处。
  • 感谢您的回复!我将比较所有这些解决方案。并感谢第二个(设置)列表技巧。
【解决方案4】:
list = [1,2,4,5,7,8,10]

d = 3

# python 3 required for _
result = len([_ for x in range(len(list))
                if list[x]+d in list and list[x]+2*d in list])
# python 2
result = len([1 for x in range(len(list))
                if list[x]+d in list and list[x]+2*d in list])

【讨论】:

  • 抛出错误:NameError: name '_' is not defined
  • @sword1st 刚刚检查过。 _ 需要 python 3,对于 python 2,它会抛出 NameError
【解决方案5】:

如果您只需要发生的次数,请返回列表的长度:

len([count for x in range(len(list)) 
           if list[x]+d in list and list[x]+2*d in list])

记住这是一个列表理解;您不能添加任意操作。例如赋值。

【讨论】:

  • 感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 2020-05-23
  • 2021-09-11
  • 1970-01-01
  • 2013-03-06
相关资源
最近更新 更多