2017-03-03 66 views
6

我在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 

但我不知道是否会有一个更好的(更短?)做同样的事情的方式。

回答

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

注意,这将只返回空列表时,目标元素是不是在列表中。

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

首先,由enumerate(l)第二项itertools.groupby(enumerate(l), lambda x: x[1])意愿组,但保留项目的索引。

然后[list(j) for i,j in itertools.groupby(enumerate(l), lambda x: x[1]) if i==0]将只保留0值。

最后,由于list(j)消耗itertools对象,所以需要最后的列表理解。

+0

事实上,它可以用'itertools'在一行中完成。我会研究这个图书馆。谢谢 ! – Odile

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

另一个oneliner与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将返回(index, value)元组,然后由该值进行分组。 groupby返回(key, iterable)元组,如果密钥不为零,则该组将被丢弃。对于保留的组next用于拉出组中的第一个项目并从那里获取索引,其余项目由给定为sum的生成器表达式处理以获得计数。

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

计数零的数目有从当前位置到右侧。

虽然清楚,但这种解决方案的缺点是,它在处理它之前需要整个列表。