2010-08-30 3 views
1

Il doit y avoir une façon plus simple et plus pythonique de le faire.Python: recherche de changement séquentiel dans un membre de paires de listes, signalez autre

Compte tenu de cette liste de paires:

pp = [('a',1),('b',1),('c',1),('d',2),('e',2)] 

Comment puis-je trouver plus facilement le premier élément de paires adjacentes où le deuxième élément change (ici, de 1 à 2). Donc je cherche ['c', 'd']. Supposons qu'il n'y aura qu'un seul changement dans la paire [1] pour la liste entière, mais qu'il peut s'agir d'une chaîne.

Ce code fonctionne mais semble atrocement long et encombrant.

for i, pair in enumerate(pp): 
    if i == 0: 
     pInitial = pair[0] 
     sgInitial = pair[1] 
    pNext = pair[0] 
    sgNext = pair[1] 
    if sgInitial == sgNext: 
     sgInitial = sgNext 
     pInitial = pNext 
    else: 
     pOne = pInitial 
     pTwo = pNext 
     x = [pOne, pTwo] 
     print x 
     break 

Merci Tim

Répondre

2
import itertools as it 

pp = [('a',1),('b',1),('c',1),('d',2),('e',2)] 

# with normal zip and slicing 
for a,b in zip(pp,pp[1:]): 
    if a[1] != b[1]: 
     x=(a[0],b[0]) 
     print x 
     break 
# with generators and izip 
iterfirst = (b for a,b in pp) 
itersecond = (b for a,b in pp[1:]) 
iterfirstsymbol = (a for a,b in pp) 
itersecondsymbol = (a for a,b in pp[1:]) 
iteranswer = it.izip(iterfirstsymbol, itersecondsymbol, iterfirst, itersecond) 

print next((symbol1, symbol2) 
      for symbol1,symbol2, first, second in iteranswer 
      if first != second) 

ajouté ma version lisible générateur.

+0

J'aime la façon dont vous traitez la liste comme deux listes, la seconde commençant simplement au deuxième tuple. Merci! – Tim

+0

Découvrez également ma réponse sur d'autres threads: http://stackoverflow.com/questions/3460161/remove-adjacent-duplicate-elements-from-a-list/3463143#3463143 Voir la similarité? –

0

Vous pouvez essayer somethingl comme:

[[pp[i][0],pp[i+1][0]] for i in xrange(len(pp)-1) if pp[i][1]!=pp[i+1][1]][0] 

(en utilisant la compréhension de la liste)

+0

Merci, la compréhension des listes semble être une bonne façon de procéder. – Tim

0

essayez de comparer pp[:-1]-pp[1:], quelque chose comme

[a for a in zip(pp[:-1], pp[1:]) if a[0][1] != a[1][1]] 

(voir zip(pp[:-1], pp[1:]) d'abord pour voir ce qui se passe

modifier:

je suppose que vous auriez besoin

([a[0][0], a[1][0]] for a in zip(pp[:-1], pp[1:]) if a[0][1] != a[1][1]).next() 
0
>>> import itertools 
>>> pp = [('a',1),('b',1),('c',1),('d',2),('e',2)] 
>>> gb = itertools.groupby(pp, key=lambda x: x[1]) 
>>> f = lambda x: list(next(gb)[1])[x][0] 
>>> f(-1), f(0) 
('c', 'd') 
0

Voici quelque chose (simple?) Avec récursion:

def first_diff(seq, key=lambda x:x): 
    """ returns the first items a,b of `seq` with `key(a) != key(b)` """ 
    it = iter(seq) 
    def test(last): # recursive function 
     cur = next(it) 
     if key(last) != key(cur): 
      return last, cur 
     else: 
      return test(cur) 
    return test(next(it)) 

print first_diff(pp, key=lambda x:x[1]) # (('c', 1), ('d', 2)) 
0
pp = [('a',1),('b',1),('c',1),('d',2),('e',2)] 
def find_first(pp): 
    for i,(a,b) in enumerate(pp): 
     if i == 0: oldb = b 
     else: 
      if b != oldb: return i 
    return None 
print find_first(pp) 
0
>>> pp = [('a',1),('b',1),('c',1),('d',2),('e',2)] 
>>> [[t1, t2] for ((t1, v1), (t2, v2)) in zip(pp, pp[1:]) if v1 != v2] [0] 
['c', 'd'] 
>>> 

J'aime pour plus de clarté ... si vous trouvez la liste compréhensions claire. Il crée deux listes temporaires: pp [1:] et le résultat zip(). Puis il compare tous les paires adjacentes et vous donne le premier changement trouvé.

Cette expression du générateur similaire prospectifs ne crée pas de listes temporaires et arrête le traitement lorsqu'il atteint le premier changement:

>>> from itertools import islice, izip 
>>> ([t1, t2] for ((t1, v1), (t2, v2)) in izip(pp, islice(pp, 1, None)) 
...   if v1 != v2 
...).next() 
['c', 'd'] 
>>> 

exemples de Tout le monde sur cette page sont plus compacts que ce qu'ils seraient si vous vouliez attraper les erreurs.

Questions connexes