2010-10-19 12 views
6

mam listę w następujący sposób:Python: ustalić długość sekwencji równych elementów w liście

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 

Chcę ustalić długość sekwencji równych elementów, to znaczy do podanej listy Chcę wyjście być:

[(0, 6), (1, 6), (0, 4), (2, 3)] 

(lub podobnym formatem).

Pomyślałem o użyciu defaultdict, ale zlicza on wystąpienia każdego elementu i gromadzi go dla całej listy, ponieważ nie mogę mieć więcej niż jednego klucza "0".

Teraz moje rozwiązanie wygląda tak:

out = [] 
cnt = 0 

last_x = l[0] 
for x in l: 
    if x == last_x: 
     cnt += 1 
    else: 
     out.append((last_x, cnt)) 
     cnt = 1 
    last_x = x 
out.append((last_x, cnt)) 

print out 

Zastanawiam się, czy istnieje bardziej pythonic sposób to zrobić.

Odpowiedz

13

Prawie na pewno chcesz używać itertools.groupby:

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
answer = [] 
for key, iter in itertools.groupby(l): 
    answer.append((key, len(list(iter)))) 

# answer is [(0, 6), (1, 6), (0, 4), (2, 3)] 

Jeśli chcesz uczynić go bardziej pamięć wydajny, jeszcze dodać więcej złożoność, można dodać funkcję Długość:

def length(l): 
    if hasattr(l, '__len__'): 
     return len(l) 
    else: 
     i = 0 
     for _ in l: 
      i += 1 
     return i 

l = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
answer = [] 
for key, iter in itertools.groupby(l): 
    answer.append((key, length(iter))) 

# answer is [(0, 6), (1, 6), (0, 4), (2, 3)] 

Uwaga chociaż że nie porównałem funkcji length() i jest całkiem możliwe, że spowolni to.

+0

Można nieco przyspieszyć klauzulę 'else:', zastępując to, co jest widoczne z następującymi dwoma liniami: 'dla i, _ w wyliczeniu (l, 1): pass', po którym następuje' return i'. – martineau

3

odpowiedź Mike'a jest dobra, ale itertools._grouper zwrócony przez GroupBy nigdy nie będzie mieć metodę __len__ więc nie ma testowanie punkt za to

używam sum(1 for _ in i) aby uzyskać długość itertools._grouper

>>> import itertools as it 
>>> L = [0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2] 
>>> [(k, sum(1 for _ in i)) for k, i in it.groupby(L)] 
[(0, 6), (1, 6), (0, 4), (2, 3)] 
+1

. . . bardzo dobrze! – mshsayem

Powiązane problemy