2016-07-09 10 views
9

Ich versuche ein neues Tupel zu einer Liste von Tupeln hinzuzufügen (sortiert nach dem ersten Element in Tupel), wobei das neue Tupel Elemente sowohl des vorherigen als auch des nächsten Elements enthält In der Liste.Insert-Element zum Auflisten basierend auf vorherigen und nächsten Elementen

Beispiel:

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

(4,10), wurde konstruiert aus und addiert dazwischen (3, 10 ) und (4 , 7).

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

Ich habe versucht() mit aufzählen an der spezifischen Position einfügen, aber das ist nicht wirklich lassen Sie mich das nächste Element zugreifen.

+0

Was ist die Eingabe des Benutzers? die neue Position der neuen Ulme? –

+0

Der Benutzer stellt nur die ursprüngliche "oldList" zur Verfügung. Dann wird zwischen jeweils zwei alten Elementen ein neues Element hinzugefügt, basierend auf den zwei vorhandenen Elementen. –

Antwort

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

die Ihnen:

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

Offensichtlich benötigen wir einige Fehler tun Umgang mit verschiedenen möglichen Situationen zu bewältigen.

Sie könnten auch tun es eine einzige Iterator, wenn Sie bevorzugen:

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

Sie itertools.tee an Ort und Stelle verwenden können iter des Aufrufs:

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

Vielen Dank, das funktioniert wie ein Zauber. Wie würde die Fehlerbehandlung diese Methode verbessern, während sie für meine aktuelle Liste funktioniert? –

+0

@SilviuTofan, wirklich nur Dinge wie das Auffangen leerer/einzelner Tupel etc .. wie du damit umgehst würdest es abhängen, was du in diesen Situationen passieren willst –

+0

Ah, ok, das macht Sinn, danke! –

5

Sie können eine Liste Verständnis verwenden und 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

Vielen Dank auch für Ihre Antwort! Ich bin nur dazu gekommen, das andere zu implementieren, da es etwas früher veröffentlicht wurde als deines. –

3

Nicht ein großer Fan von Einzeilern (oder Komplexität) selbst, ich werde eine sehr explizite und lesbare (was normalerweise eine gute Sache ist!) Lösung für Ihr Problem vorschlagen.

So in sehr vereinfachenden Ansatz, könnten Sie dies tun:

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) 

Das wird Ihnen das gewünschte Ergebnis in newList:

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

Das ist nicht viel mehr Code als andere ausgereiftere (und speichereffiziente!) Lösungen, wie die Verwendung von Generatoren, UND ich halte es für viel leichter zu lesen als komplizierte Einzeiler. Außerdem wäre es leicht, dieser einfachen Funktion einige Überprüfungen hinzuzufügen (z. B. um sicherzustellen, dass Sie eine Liste von Tupeln haben).

Sofern Sie nicht bereits wissen, dass Sie dieses bestimmte Teil Ihres Codes optimieren müssen (vorausgesetzt, dies ist Teil eines größeren Projekts), sollte dies good enough sein. Zur gleichen Zeit ist es: einfach zu implementieren, einfach zu lesen, einfach zu erklären, einfach zu warten, einfach zu erweitern, einfach zu refactor, etc.

Hinweis: alle anderen früheren Antworten auf Ihre Frage sind auch bessere Lösungen als diese einfache, in vielerlei Hinsicht. Ich wollte dir nur eine andere Wahl geben. Hoffe das hilft.

+0

Vielen Dank, ich schätze diese Antwort auch sehr, es macht ein sehr einfach zu lesendes und einfach zu implementierendes Stück Code! –

Verwandte Themen