我正在尝试创建一个列表(例如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
函数)吗?
答案 0 :(得分:6)
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
将值限制在0
和1
之间:
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])
groupby
和ngroup
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.groupby
,numpy
或简单的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
当出现这种需要时,True
和False
的值分别变成1
和0
sum
函数的工作原理:实际上,类似sum([3,4])
的意思是计算0+3+4
,因此sum([True,True])
意味着计算0+True+True
,它被转换为{{1} }