将数组值的增量减少到1

时间:2019-01-09 14:44:04

标签: python list numpy

我正在尝试创建一个列表(例如B),该列表仅在另一个列表(例如A)的值存在差异时才递增,例如:

[1,1,2,2,4,4][0,0,1,1,2,2]

[1,1,1,1,4,4,4,4][0,0,0,0,1,1,1,1]

以下代码可以做到:

boxes=[1,1,1,1,4,4,4,4]
positions=[0]
position=0
for psn,box in list(enumerate(boxes))[:-1]:
    if boxes[psn+1]-box ==0:
        increment=0
    else:
        increment=1
    position=position+increment
    positions.append(position)
print(positions)

有人可以建议使用列表推导(最好使用lambda函数)吗?

5 个答案:

答案 0 :(得分:6)

使用itertools.groupby

from itertools import groupby

a = [1,1,2,2,4,4]

result = [i for i, (_, group) in enumerate(groupby(a)) for _ in group]
print(result)

输出

[0, 0, 1, 1, 2, 2]

答案 1 :(得分:6)

这是使用nummpy的一种方式:

a = [1,1,2,2,4,4]
[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 1, 1, 2, 2]

或者在另一个示例中:

a = [1,1,1,1,4,4,4,4]
[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 0, 0, 1, 1, 1, 1]

详细信息

a = [1,1,2,2,4,4]

使用np.diff

获得数组的第一个差异
np.diff(a)
array([0, 1, 0, 2, 0]) 

并使用np.clip将值限制在01之间:

np.clip(np.diff(a), 0, 1)
array([0, 1, 0, 1, 0])

最后取np.cumsum并在开头添加一个0,因为差异将为您提供长度为n-1的数组:

[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 1, 1, 2, 2]

答案 2 :(得分:3)

我看到了很多解决方案,所以我们开始吧。

digitize

np.digitize(A, np.unique(A)) - 1
# array([0, 0, 0, 0, 1, 1, 1, 1])

factorize

import pandas 
pd.factorize(A)[0]
# array([0, 0, 0, 0, 1, 1, 1, 1])

groupbyngroup

pd.Series(A).groupby(A).ngroup()

0    0
1    0
2    0
3    0
4    1
5    1
6    1
7    1
dtype: int64

unique

np.unique(A, return_inverse=True)[1]
# array([0, 0, 0, 0, 1, 1, 1, 1])

将列表理解与itertools.accumulate一起使用:

from itertools import accumulate
from operator import add

list(accumulate([0] + [x != y for x, y in zip(A, A[1:])], add))
# [0, 0, 0, 0, 1, 1, 1, 1]

答案 3 :(得分:2)

您无法使用传统的列表理解来做到这一点,因为它们无法share a mutable state between iterations

在这种情况下,建议使用itertools.groupbynumpy或简单的python循环(如您的代码所示)。

但是,如果您真的想使用列表理解,一种方法是依靠副作用。

例如:

boxes=[1,1,1,1,4,4,4,4]
positions = [0]
throwaway = [
    positions.append(positions[-1] + 0 if boxes[psn+1]-box == 0 else 1) 
    for psn, box in enumerate(boxes[:-1])
]
print(positions)
#[0, 0, 0, 0, 1, 1, 1, 1]

您正在使用列表理解来创建名为throwaway的列表,但是throwaway的实际内容根本没有用。我们使用迭代来调用append上的positions。由于append返回None,因此以下是列表理解的实际结果。

print(throwaway)
#[None, None, None, None, None, None, None]

但是,依靠这种副作用被认为不是好习惯。

答案 4 :(得分:2)

使用zip并列出理解和切片的方法

a = [1,1,2,2,4,4]
increments = [bool(i[1]-i[0]) for i in zip(a,a[1:])]
b = [sum(increments[:i]) for i in range(len(increments)+1)]
print(b) #prints [0, 0, 1, 1, 2, 2]

说明:此解决方案依赖于Python:

在向0函数提要时,除0.0(或True)以外的任何数字都将被评估为bool

当出现这种需要时,TrueFalse的值分别变成10

sum函数的工作原理:实际上,类似sum([3,4])的意思是计算0+3+4,因此sum([True,True])意味着计算0+True+True,它被转换为{{1} }