2016-07-07 67 views

risposta

38

Cleaner approccio Pythonic:

>>> [(x,y) for x,y in zip(myList, myList[1:]) if y == 9] 
[(8, 9), (4, 9), (7, 9)] 

Qual è il codice di cui sopra fare:

  • zip(some_list, some_list[1:]) sarebbe generare un elenco di coppie di elementi adiacenti.
  • Ora con quella tupla, filtro a condizione che il secondo elemento sia uguale a 9. Il gioco è fatto :)
7

Si erano abbastanza vicino, vi mostrerò un modo alternativo che potrebbe essere più intuitiva se si sta appena iniziando:

sets = [(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9] 

ottenere l'indice nel intervallo della lunghezza dell'elenco e se il valore nella posizione i è uguale a 9, afferrare gli elementi adiacenti.

Il risultato è:

sets 
[(8, 9), (4, 9), (7, 9)] 

Questo è meno efficiente rispetto agli altri approcci ma ho deciso di non-eliminarlo visualizzare un modo diverso di farlo. È possibile farlo andare un po 'più veloce utilizzando enumerate() invece:

sets = [(myList[i-1], j) for i, j in enumerate(myList) if j == 9] 

Prendere nota che nel caso bordo dove myList[0] = 9 il comportamento della comprensione, senza zip e il comportamento del comprensione con zip è diverso.

In particolare, se myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8] poi:

[(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9] 
# results in: [(8, 9), (8, 9), (4, 9), (7, 9)] 

mentre:

[(x, y) for x, y in zip(myList, myList[1:]) if y==9] 
# results in: [(8, 9), (4, 9), (7, 9)] 

Spetta a voi decidere quale di questi si adatta alle vostre criteri, sto solo sottolineando che don' si comportano allo stesso modo in tutti i casi.

17

Parte del problema è che myList[i:i] restituirà sempre una lista vuota. La fine di una fetta è esclusivo, in modo che quando si fa a_list[0:0] si sta cercando di prendere gli elementi di a_list che esistono tra indice 0 e l'indice 0.

Sei sulla strada giusta, ma si vuole comprimi l'elenco con se stesso.

[(x, y) for x, y in zip(myList, myList[1:]) if y==9] 
+0

completamente identica alla mia risposta :) – SuperSaiyan

+7

@SuperSaiyan eccezione del fatto che il vostro non parlare del problema principale del PO ha avuto, il loro utilizzo di 'myList [i: i]'. –

+0

Lettura correlata per l'OP [Spiegazione della notazione slice di Python] (http://stackoverflow.com/q/509211) –

5

È anche possibile farlo senza affettare da iteratori creando:

l = myList = [1,8,9,2,4,9,6,7,9,8] 

it1, it2 = iter(l), iter(l) 
# consume first element from it2 -> leaving 8,9,2,4,9,6,7,9,8 
next(it2, "") 
# then pair up, (1,8), (8,9) ... 
print([(i, j) for i,j in zip(it1, it2) if j == 9]) 

o utilizzare il pairwise recipe per creare le coppie

from itertools import tee, izip 

def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return izip(a, b) 

Se si utilizza python3, basta importare tee e utilizzare il regolare zip.

+0

isnt una lista già iterabile, perché iter (l), iter (l)? –

+0

@Phillip, quando si consuma una parte di un iteratore, ad esempio (it2), si passa all'elemento successivo e il primo viene consumato, quindi in questo esempio partiamo dal secondo elemento per it2 quando eseguiamo il comando zip –

5

È davvero sorprendente che nessuno abbia aggiunto un approccio funzionale.

Un'altra risposta alternativa è l'utilizzo di filter. Questa funzione built restituisce un iteratore (elenco python2) costituito da tutti gli elementi presenti nella lista che restituiscono True per una particolare funzione

>>> myList = [1,8,9,2,4,9,6,7,9,8] 
>>> list(filter(lambda x:x[1]==9,zip(myList, myList[1:]))) 
[(8, 9), (4, 9), (7, 9)] 

Si deve notare che il list call is needed only in python3+. La differenza tra l'approccio funzionale e la comprensione delle liste è discussa in detail in this post.

1

La mia soluzione è simile a uno dei Jim avanzato con verifica di zero-index

myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8] 

[(myList[i-1], x) for i, x in enumerate(myList) if x==9 and i!=0] 

# [(8, 9), (4, 9), (7, 9)]