2016-07-09 20 views
9

Sto tentando di aggiungere una nuova tupla a un elenco di tuple (ordinate per primo elemento in tupla), dove la nuova tupla contiene elementi sia dell'elemento precedente che di quello successivo nella lista.Inserisci elemento da elencare in base agli elementi precedenti e successivi

Esempio:

oldList = [(3, 10), (4, 7), (5,5)] 
newList = [(3, 10), (4, 10), (4, 7), (5, 7), (5, 5)] 

(4,10) è stato costruito da e aggiunti tra (3, 10 ) e (4 , 7).

Construct (x,y) from (a,y) and (x,b) 

Ho provato con enumerare() per inserire nella posizione specifica, ma che in realtà non mi permetta di accedere all'elemento successivo.

+0

Qual è l'input dell'utente? la nuova posizione del nuovo olmo? –

+0

L'utente fornisce solo la "lista vecchia" iniziale. Quindi, tra ogni 2 vecchi elementi, viene aggiunto un nuovo elemento in base ai due esistenti. –

risposta

8
oldList = [(3, 10), (4, 7), (5,5)] 

def pair(lst): 
    # create two iterators 
    it1, it2 = iter(lst), iter(lst) 
    # move second to the second tuple 
    next(it2) 
    for ele in it1: 
     # yield original 
     yield ele 
     # yield first ele from next and first from current 
     yield (next(it2)[0], ele[1]) 

che vi darà:

In [3]: oldList = [(3, 10), (4, 7), (5, 5)] 

In [4]: list(pair(oldList)) 
Out[4]: [(3, 10), (4, 10), (4, 7), (5, 7), (5, 5)] 

Ovviamente abbiamo bisogno di fare un po 'di movimentazione per gestire diverse situazioni possibili errori.

Si potrebbe anche farlo utilizzando un singolo iteratore se si preferisce:

def pair(lst): 
    it = iter(lst) 
    prev = next(it) 
    for ele in it: 
     yield prev 
     yield (prev[0], ele[1]) 
     prev = ele 
    yield (prev[0], ele[1]) 

È possibile utilizzare itertools.tee al posto di chiamare iter:

from itertools import tee 
def pair(lst): 
    # create two iterators 
    it1, it2 = tee(lst) 
    # move second to the second tuple 
    next(it2) 
    for ele in it1: 
     # yield original 
     yield ele 
     # yield first ele from next and first from current 
     yield (next(it2)[0], ele[1]) 
+1

Grazie mille, questo funziona come un fascino. Mentre funziona per il mio elenco corrente, in che modo la gestione degli errori migliorerebbe questo metodo? –

+0

@SilviuTofan, davvero solo cose come catturare tuple vuote/singole ecc .. come lo gestisci dipenderà da cosa vuoi che succeda in quelle situazioni –

+0

Ah, ok, questo ha senso, grazie! –

5

È possibile utilizzare un elenco di comprensione e itertools.chain():

>>> list(chain.from_iterable([((i, j), (x, j)) for (i, j), (x, y) in zip(oldList, oldList[1:])])) + oldList[-1:] 
[(3, 10), (4, 10), (4, 7), (5, 7), (5, 5)] 
+0

Grazie anche per la risposta! Ho solo avuto modo di implementare l'altro dato che è stato pubblicato poco prima del tuo. –

3

Non essendo un grande fan di one-liner (o complessità), proporrò una soluzione molto esplicita e leggibile (che di solito è una buona cosa!) al tuo problema.

Così, in un approccio molto semplicistico, si potrebbe fare questo:

def insertElements(oldList): 
    """ 
    Return a new list, alternating oldList tuples with 
    new tuples in the form (oldList[i+1][0],oldList[i][1]) 
    """ 
    newList = [] 
    for i in range(len(oldList)-1): 
     # take one tuple as is 
     newList.append(oldList[i]) 
     # then add a new one with items from current and next tuple 
     newList.append((oldList[i+1][0],oldList[i][1])) 
    else: 
     # don't forget the last tuple 
     newList.append(oldList[-1]) 
    return newList 

oldList = [(3, 10), (4, 7), (5, 5)] 
newList = insertElements(oldList) 

che vi darà il risultato desiderato in newList:

print(newList) 
[(3, 10), (4, 10), (4, 7), (5, 7), (5, 5)] 

Questo non è il codice molto più lungo altre soluzioni più sofisticate (ed efficienti in termini di memoria!), come l'utilizzo di generatori, E lo considero molto più facile da leggere rispetto alle intricate one-liner. Inoltre, sarebbe facile aggiungere alcuni controlli a questa semplice funzione (come assicurarsi di avere una lista di tuple).

A meno che non si sappia già che è necessario ottimizzare questo particolare pezzo del codice (supponendo che faccia parte di un progetto più grande), questo dovrebbe essere good enough. Allo stesso tempo è: facile da implementare, facile da leggere, facile da spiegare, facile da mantenere, facile da estendere, facile da refactoring, ecc.

Nota: tutte le altre risposte precedenti alla tua domanda sono anche soluzioni migliori di questa semplice, in molti modi. Volevo solo darti un'altra scelta. Spero che questo ti aiuti.

+0

Grazie, apprezzo molto anche questa risposta, è un pezzo di codice molto facile da leggere e facile da implementare! –

Problemi correlati