2017-03-03 115 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:]))) 

計數零的數目有從當前位置到右側。

雖然清楚,但這種解決方案的缺點是,它在處理它之前需要整個列表。