我正在使用Python并考虑以下问题:给定一个列表,例如[1, 0, -2, 0, 0, 4, 5, 0, 3]
多次包含整数0,我希望索引位于这些0和每一个,它出现在列表中的次数,直到出现不同的元素或列表结束。
给定l = [1, 0, -2, 0, 0, 4, 5, 0]
,函数将返回((1, 1), (3, 2), (7, 1))
。结果是一个元组列表。元组的第一个元素是给定元素的索引(在列表中),第二个元素是在不同元素出现或列表结束之前重复的次数。
天真地,我会写这样的东西:
def myfun(l, x):
if x not in l:
print("The given element is not in list.")
else:
j = 0
n = len(l)
r = list()
while j <= (n-2):
count = 0
if l[j] == x:
while l[j + count] == x and j <= (n-1):
count +=1
r.append((j, count))
j += count
else:
j += 1
if l[-1] == x:
r.append((n-1, 1))
return r
但是我想知道是否会有更好的(更短的?)方式做同样的事情。
答案 0 :(得分:4)
不是最漂亮的,而是一个单行:
>>> import itertools
>>> l=[1, 0, -2, 0, 0, 4, 5, 0]
>>> [(k[0][0],len(k)) for k in [list(j) for i,j in itertools.groupby(enumerate(l), lambda x: x[1]) if i==0]]
[(1, 1), (3, 2), (7, 1)]
首先,itertools.groupby(enumerate(l), lambda x: x[1])
将按enumerate(l)
的第二项进行分组,但保留该项的索引。
然后[list(j) for i,j in itertools.groupby(enumerate(l), lambda x: x[1]) if i==0]
将只保留0个值。
最后,需要最后一个列表理解,因为list(j)
使用了itertools对象。
答案 1 :(得分:3)
另一个groupby
的oneliner,没有使用中间列表:
>>> from itertools import groupby
>>> l = [1, 0, -2, 0, 0, 4, 5, 0, 3]
>>> [(next(g)[0], 1 + sum(1 for _ in g)) for k, g in groupby(enumerate(l), key=lambda x: x[1]) if k == 0]
[(1, 1), (3, 2), (7, 1)]
在上面enumerate
将返回(index, value)
个元组,然后按值对其进行分组。 groupby
返回(key, iterable)
个元组,如果key为非零,则该组将被丢弃。对于保留的组next
用于拉出组中的第一个项目并从那里获取索引,而其余项目由给予sum
的生成器表达式处理以获得计数。
答案 2 :(得分:1)
一个选项是让itertools.groupby
根据条件为您分割列表:
import itertools
def myfun(l, x):
result = []
currentIdx = 0
# group by condition:
for isZero, group in itertools.groupby(i==x for i in l):
groupLen = len(list(group))
if isZero: result.append((currentIdx, groupLen))
currentIdx += groupLen
return result
l=[1, 0, -2, 0, 0, 4, 5, 0]
print(myfun(l, 0))
请注意,当目标元素不在列表中时,这将返回空列表。
答案 3 :(得分:1)
我就是这样做的
l=[1, 0, -2, 0, 0, 4, 5, 0]
lis=[]
t=0
for m in range(len(l)):
if l[m]==0:
if t==0:
k=m
j=1
t=1
else:
j=j+1
t=1
if m==len(l)-1:
lis.append((k,j))
else:
if t==1:
t=0
lis.append((k,j))
答案 4 :(得分:1)
另一种解决方案,使用itertools.takewhile
:
from itertools import takewhile
L = [1, 0, -2, 0, 0, 4, 5, 0]
res = []
i = 0
while i < len(L):
if L[i] == 0:
t = len(list(takewhile(lambda k: k == 0, L[i:])))
res.append((i, t))
i += t
else:
i += 1
print(res)
该行
t = len(list(takewhile(lambda k: k == 0, L[i:])))
计算从当前位置到右边的零的数量。
虽然足够清楚,但这个解决方案的缺点是它在处理之前需要整个列表。