在列表中查找项目和重复项。

6
我正在使用Python编程,考虑以下问题:给定一个列表,例如[1, 0, -2, 0, 0, 4, 5, 0, 3],其中包含多个整数0。我想要获得这些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

但是我想知道是否有更好(更短?)的方法来完成同样的事情。

4个回答

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 对象。

确实,可以使用 itertools 在一行代码中完成。我会研究一下这个库。谢谢! - Odile

3

使用groupby进行一行代码的分组,无需使用中间列表:

>>> 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将返回(索引, 值)元组,然后根据值进行分组。 groupby返回(键,可迭代对象)元组,如果键为非零,则该组被丢弃。对于保留的组,使用next来提取组中的第一项并从那里获取索引,而其余项由生成器表达式传递给sum以获得计数。


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))

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:])))

计算当前位置到右侧的零的数量。

虽然这个解决方案足够清晰,但其缺点是需要在处理之前获取整个列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接