2010-10-19 14 views
6

j'ai une liste comme suit:python: déterminer la longueur de la séquence d'éléments égaux dans la liste

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

je souhaite déterminer la longueur d'une séquence d'éléments identiques, à savoir pour la liste donnée je veux la sortie être:

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

(ou un format similaire).

J'ai pensé à utiliser un defaultdict mais il compte les occurrences de chaque élément et l'accumule pour la liste entière, puisque je ne peux pas avoir plus d'une clé '0'.

En ce moment, ma solution ressemble à ceci:

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 

Je me demande s'il y a un moyen plus pythonique de le faire.

Répondre

13

Vous presque sûrement envie d'utiliser 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)] 

Si vous voulez le rendre plus efficace de la mémoire, encore ajouter plus de complexité, vous pouvez ajouter une fonction de longueur:

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

Remarque si que je n'ai pas référencé la fonction length(), et il est tout à fait possible que cela vous ralentisse.

+0

Vous pourriez accélérer la clause 'else:' en remplaçant ce qui est montré par les deux lignes suivantes: 'pour i, _ dans enumerate (l, 1): pass' suivi de' return i'. – martineau

3

La réponse de Mike est bon, mais le itertools._grouper retourné par groupby aura jamais une méthode __len__ donc il n'y a pas de test de point pour elle

J'utilise sum(1 for _ in i) pour obtenir la longueur de la 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

. . . très agréable! – mshsayem