如何在Python的列表理解中执行以下操作?
nums = [1,1,0,1,1]
oFlag = 1
res = []
for x in nums:
if x == 0:
oFlag = 0
res.append(oFlag)
print(res)
# Output: [1,1,0,0,0]
实际上,在本例中,一旦发生0
,列表的其余部分就会清零。
发布于 2018-09-20 06:00:34
在某些上下文中,列表理解是存在于许多函数式编程语言中的map
和filter
函数的一种“命令式”语法。您尝试执行的操作通常称为accumulate
,这是一个稍有不同的操作。您不能用map
和filter
来实现accumulate
,除非使用副作用。Python允许你在列表理解中有副作用,所以这绝对是可能的,但是有副作用的列表理解有点不可靠。下面是如何使用accumulate实现此功能:
nums = [1,1,0,1,1]
def accumulator(last, cur):
return 1 if (last == 1 and cur == 1) else 0
list(accumulate(nums, accumulator))
或者一行:
list(accumulate(nums, lambda last, cur: 1 if (last == 1 and cur == 1) else 0))
当然,有几种方法可以使用外部状态和带有副作用的列表理解来做到这一点。这里有一个例子,它有点冗长,但非常明确地说明了状态是如何被操纵的:
class MyState:
def __init__(self, initial_state):
self.state = initial_state
def getNext(self, cur):
self.state = accumulator(self.state, cur)
return self.state
mystate = MyState(1)
[mystate.getNext(x) for x in nums]
发布于 2018-09-20 06:06:13
我有一个使用列表理解的答案,但@Prune抢先了我一步。这真的只是一条警示的尾巴,显示了如何在反对该方法的同时完成它。
以下是一种可能适合您需求的替代方法:
import itertools
import operator
nums = [1,1,0,1,1]
res = itertools.accumulate(nums, operator.and_)
在本例中,res
是一个可迭代的。如果你需要一个列表,那么
res = list(itertools.accumulate(nums, operator.and_))
让我们来分析一下。accumulate()
函数可用于生成运行总数或“累积和”。如果只传递了一个参数,则默认函数为addition。这里我们传入operator.and_。operator
模块导出一组与Python的内部运算符相对应的高效函数。当在0和1的列表上运行累加的and
时,结果是一个列表,在找到第一个0之前是1,然后是所有0。
当然,我们并不局限于使用operator
模块中定义的函数。您可以使用任何接受第一个参数中元素类型的2个参数的函数(并且可能返回相同的类型)。您可以发挥创造力,但在这里我将保持简单,只实现and
import itertools
nums = [1,1,0,1,1]
res = itertools.accumulate(nums, lambda a, b: a and b)
注意:使用operator.and_可能运行得更快。在这里,我们只是提供一个使用lambda语法的示例。
虽然没有使用列表理解,但对我来说有类似的感觉。它只有一行,读起来不是很难。
发布于 2018-09-20 05:39:25
对于列表理解方法,您可以结合使用index
和enumerate
firstIndex = nums.index(0) if 0 in nums else -1
[1 if i < firstIndex else 0 for i, x in enumerate(nums)]
另一种使用numpy
的方法
import numpy as np
print(np.cumprod(np.array(nums) != 0).tolist())
#[1, 1, 0, 0, 0]
在这里,我们将nums
转换为numpy数组,并检查这些值是否不等于0。然后我们得到数组的累积乘积,知道一旦找到0,我们就会从那个点开始乘以0。
https://stackoverflow.com/questions/52414505
复制相似问题