我有这个问题。
让 l
是一个只包含 0 和 1 的列表,找到所有表示 1 重复序列开始和结束的元组。
例子
l=[1,1,0,0,0,1,1,1,0,1]
回答:[(0,2),(5,8),(9,10)]
我用下面的代码解决了这个问题,但我认为它很困惑,我想知道是否有更简洁的方法来解决这个问题(也许使用 map/reduce ?)
from collections import deque
def find_range(l):
pairs=deque((i,i+1) for i,e in enumerate(l) if e==1)
ans=[]
p=[0,0]
while(len(pairs)>1):
act=pairs.popleft()
nex=pairs[0]
if p==[0,0]:
p=list(act)
if act[1]==nex[0]:
p[1]=nex[1]
else:
ans.append(tuple(p))
p=[0,0]
if(len(pairs)==1):
if p==[0,0]:
ans.append(pairs.pop())
else:
ans.append((p[0],pairs.pop()[1]))
return ans
最佳答案
与 itertools.groupby
魔法:
from itertools import groupby
lst = [1, 1, 0, 0, 0, 1, 1, 1, 0, 1]
indices, res = range(len(lst)), []
for k, group in groupby(indices, key=lambda i: lst[i]):
if k == 1:
group = list(group)
sl = group[0], group[-1] + 1
res.append(sl)
print(res)
输出:
[(0, 2), (5, 8), (9, 10)]
或者用更多 高效 生成器功能:
def get_ones_coords(lst):
indices = range(len(lst))
for k, group in groupby(indices, key=lambda i: lst[i]):
if k == 1:
group = list(group)
yield group[0], group[-1] + 1
lst = [1, 1, 0, 0, 0, 1, 1, 1, 0, 1]
print(list(get_ones_coords(lst))) # [(0, 2), (5, 8), (9, 10)]
简而言之 奖金 ,这里有替代方案
numpy
方法虽然复杂,但基于连续数字之间的离散差异( numpy.diff
)和提取非零项的索引( numpy.faltnonzero
):In [137]: lst = [1,1,0,0,0,1,1,1,0,1]
In [138]: arr = np.array(lst)
In [139]: np.flatnonzero(np.diff(np.r_[0, arr, 0]) != 0).reshape(-1, 2)
Out[139]:
array([[ 0, 2],
[ 5, 8],
[ 9, 10]])
关于python - 查找一系列重复元素的更优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59119975/