首页 > 解决方案 > 基于前一个元素的列表理解 if 语句

问题描述

我有以下

U = np.array([1., 0., 0., 1., 0., 0., 1., 0., 1., 0.])
c = iter(range(2, len(U)))
result = [float(next(c)) if x == 1 else x for x in U]

这给出了
[2.0, 0.0, 0.0, 3.0, 0.0, 0.0, 4.0, 5.0, 6.0, 0.0] 但是我希望当左侧的元素是标签时,“循环”所在的数字成为相同的标签。

所以这个 [2.0, 0.0, 0.0, 3.0, 0.0, 0.0, 4.0, 4.0, 4.0, 0.0]

描述这一点的 for 循环如下:

U=np.array([1., 0., 0., 1., 1., 0., 1., 1., 1.])
l=2
for i in range(len(U[:])):  
    i+1                       #for simplicity I skipped the first one
    if U[i]==1:
        if U[i-1]!=0:
            U[i]=U[i-1]
        else:
            U[i]=l
            l+=1

这返回

array([1., 0., 0., 2., 2., 0., 3., 3., 3.])

标签: pythonnumpyif-statementlist-comprehension

解决方案


所以这里是如何处理result输出:

  • 如果输入为 0,则存储 0
  • 如果输入为 1,则存储 c 的第一个值
  • 如果输入从 1 变为 0(下降沿),则提前 c

与在 python 中一样,我们无法检查迭代器的第一个元素,因此我们需要将其放入列表或任何其他支持它的数据结构中。要确定我们是否有下降的边缘,我们需要在一次迭代中访问两个连续的元素。

这是没有列表理解的解决方案。请注意,只要您不存储中间值,您就可以将所有内容转换为列表理解。

import numpy as np
import itertools

U = np.array([1., 0., 0., 1., 1., 0., 1., 1., 1.])
c = list(range(1, len(U)))

R = []
for U_curr, U_next in itertools.zip_longest(U, U[1:], fillvalue=0):
    if U_curr == 0:
        res.append(0)
    else:
        if U_curr == 1 and U_next == 0:
            val = c.pop(0)
        else:
            val = c[0]
        R.append(float(val))

这是列表理解中的上述内容:

U = np.array([1., 0., 0., 1., 1., 0., 1., 1., 1.])
c = list(range(1, len(U)))

R = [float(c.pop(0) if U_curr == 1 and U_next == 0 else c[0]) if U_curr != 0 else 0
     for U_curr, U_next in itertools.zip_longest(U, U[1:], fillvalue=0)]

两者都会输出

[1.0, 0, 0, 2.0, 2.0, 0, 3.0, 3.0, 3.0]

推荐阅读