2017-03-03 1 views
6

Ich arbeite in Python und unter Berücksichtigung des folgenden Problems: Angesichts einer Liste, wie [1, 0, -2, 0, 0, 4, 5, 0, 3], die die ganze Zahl 0 mehrere Male enthält, möchte ich die Indizes für diese 0 und für jede , wie oft es in der Liste erscheint, bis ein anderes Element erscheint oder die Liste endet.Suchen Sie Elemente und Wiederholungen in der Liste

Bei l = [1, 0, -2, 0, 0, 4, 5, 0] würde die Funktion zurückgeben. Das Ergebnis ist eine Liste von Tupeln. Das erste Element des Tupels ist der Index (in der Liste) des gegebenen Elements und das zweite ist die Anzahl der Wiederholungen, bis ein anderes Element erscheint oder die Liste endet.

Naiv, würde ich so etwas schreiben:

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 

Aber ich habe mich gefragt, ob es wäre ein schöner (kürzer?) Seinen Weg, um die gleiche Sache zu tun.

Antwort

1

Eine Option ist itertools.groupby aufgeteilt für die Liste zu lassen, basierend auf dem Zustand:

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

Beachten Sie, dass dies die leere Liste nur zurück, wenn das Zielelement nicht in der Liste enthalten ist.

4

nicht die schönste, aber ein Einzeiler:

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

Zuerst itertools.groupby(enumerate(l), lambda x: x[1]) Willen Gruppe durch den zweiten Punkt von enumerate(l), aber der Index des Elements halten.

Dann [list(j) for i,j in itertools.groupby(enumerate(l), lambda x: x[1]) if i==0] werden nur die 0-Werte beibehalten.

Schließlich ist das letzte Listenverständnis erforderlich, weil list(j) das itertools-Objekt konsumieren.

+0

In der Tat kann es in einer Linie mit 'itertools' getan werden.Ich werde in diese Bibliothek schauen. Vielen Dank ! – Odile

1

Dies ist, wie ich diese mit groupby

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

Einem anderen oneliner tun würde, ohne Zwischenlisten mit:

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

In oben enumerate(index, value) Tupel zurück, die durch den Wert dann gruppiert ist. groupby gibt (key, iterable) Tupel zurück, und wenn der Schlüssel ungleich Null ist, wird die Gruppe verworfen. Für gehaltene Gruppen wird next verwendet, um das erste Element in der Gruppe herauszunehmen und den Index von dort zu übernehmen, während der Rest der Elemente durch den Generator-Ausdruck sum verarbeitet wird, um die Zählung zu erhalten.

1

Eine andere Lösung, mit 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) 

Die Linie

t = len(list(takewhile(lambda k: k == 0, L[i:]))) 

zählt die Anzahl der Nullen dort von der aktuellen Position auf der rechten Seite.

Der Nachteil dieser Lösung ist klar, dass sie die gesamte Liste vor der Verarbeitung benötigt.

Verwandte Themen