Ich habe zwei Listen, von denen die erste garantiert genau einen Artikel mehr enthält als die zweite . Ich würde gerne wissen, wie man am pythonischsten eine neue Liste erstellt, deren gerade Indexwerte aus der ersten Liste und deren ungerade Indexwerte aus der zweiten Liste stammen.
# example inputs
list1 = ['f', 'o', 'o']
list2 = ['hello', 'world']
# desired output
['f', 'hello', 'o', 'world', 'o']
Das funktioniert, ist aber nicht schön:
list3 = []
while True:
try:
list3.append(list1.pop(0))
list3.append(list2.pop(0))
except IndexError:
break
Wie kann dies sonst noch erreicht werden? Was ist der pythonischste Ansatz?
Antworten:
Hier ist eine Möglichkeit, dies durch Schneiden zu tun:
quelle
Ein Rezept dafür finden Sie in der
itertools
Dokumentation :####BEARBEITEN:
Für eine Python-Version größer als 3:
quelle
zip_longest
.itertools
Dokumentation verwenden, da es.next()
nicht mehr funktioniert.__next__
. Es ist nicht in der Dokumentation geschrieben, daher habe ich eine Änderung der Antwort vorgeschlagen.Dies sollte tun, was Sie wollen:
quelle
roundrobin
Funktion für diese Situation eine Art Overkill ist.list(itertools.chain(map(next, itertools.cycle(iters)), *iters))
Ich denke, das ist die pythonischste Art, es zu tun.
quelle
None
s überschreibt , die * in der Liste enthalten sein sollen. Ich werde in einer optimierten Version bearbeiten, um dies zu behebenFalse
oder sogar Dinge , die nur werden ausgewertet , wieFalse
durch dieif
-Ausdrucks, wie zum Beispiel eines0
oder eine leere Liste. Dies kann (teilweise) durch Folgendes vermieden werden :[x for x in itertools.chain.from_iterable(itertools.zip_longest(list1, list2)) if x is not None]
. Dies funktioniert natürlich immer noch nicht, wenn die ListenNone
Elemente enthalten , die beibehalten werden müssen. In diesem Fall müssen Sie dasfillvalue
Argument von ändernzip_longest
, wie Dubslow bereits vorgeschlagen hat.None
Das Problem scheint verschwunden zu sein, zumindest seit Python 3.7.6 (ich weiß es nicht für ältere Versionen). Wennalt_chain
definiert alsdef alt_chain(*iters, fillvalue=None): return chain.from_iterable(zip_longest(*iters, fillvalue=fillvalue))
, wirdlist(alt_chain([0, False, 1, set(), 3, 4], [0, None, 1, {}], fillvalue=99))
korrekt zurückgegeben[0, 0, False, None, 1, 1, set(), {}, 3, 99, 4, 99]
.Ohne itertools und unter der Annahme, dass l1 1 Element länger als l2 ist:
Verwenden von itertools und unter der Annahme, dass Listen keine enthalten:
quelle
[(l1[0], l2[0]), (l1[1], l2[1]), ...]
.sum
verkettet Tupel miteinander:(l1[0], l2[0]) + (l1[1], l2[1]) + ...
was zu verschachtelten Listen führt. Der Rest der einzeiligen Linie besteht nur aus einer Polsterung von l1 mit einem zusätzlichen Element, damit der Reißverschluss funktioniert, und schneide bis -1, um diese Polsterung zu entfernen.filter(None, ...
(könntebool
stattdessen verwendet werden oderNone.__ne__
) falsche Werte entfernt werden, einschließlich 0, None und leere Zeichenfolgen. Der zweite Ausdruck entspricht also nicht unbedingt dem ersten.sum
das gemacht? Welche Rolle spielt dort das zweite Argument? In den Dokumentationen ist das zweite Argumentstart
.Ich weiß, dass die Fragen zwei Listen betreffen, von denen eine einen Eintrag mehr als die andere enthält, aber ich dachte, ich würde dies für andere verwenden, die diese Frage möglicherweise finden.
Hier ist Duncans Lösung, die für zwei Listen unterschiedlicher Größe geeignet ist.
Dies gibt aus:
quelle
Hier ist ein Einzeiler, der das macht:
list3 = [ item for pair in zip(list1, list2 + [0]) for item in pair][:-1]
quelle
Wenn beide Listen gleich lang sind, können Sie Folgendes tun:
Da die erste Liste ein weiteres Element enthält, können Sie es post hoc hinzufügen:
quelle
quelle
def combine(list1, list2, lst=[]):
, daher mein Kommentar. Als ich diesen Kommentar einreichte, hatte Killown die notwendigen Änderungen vorgenommen.Dieser basiert auf dem obigen Beitrag von Carlos Valiente mit der Option, Gruppen mehrerer Elemente zu wechseln und sicherzustellen, dass alle Elemente in der Ausgabe vorhanden sind:
Dadurch werden die Listen A und B nach Gruppen mit jeweils 3 Werten verschachtelt:
quelle
Meine Einstellung:
quelle
Hier ist ein Einzeiler mit Listenverständnis ohne andere Bibliotheken:
Hier ist ein anderer Ansatz, wenn Sie eine Änderung Ihrer ursprünglichen Liste1 durch Nebenwirkungen zulassen:
quelle
Könnte etwas spät sein, noch einen Python-Einzeiler zu kaufen. Dies funktioniert, wenn die beiden Listen gleich oder ungleich groß sind. Eine Sache, die nichts wert ist, ist, dass sie a und b modifiziert. Wenn es ein Problem ist, müssen Sie andere Lösungen verwenden.
quelle
quelle
Stoppt am kürzesten:
Sicher, das Auflösen der next / __ next__ -Methode kann schneller sein.
quelle
Das ist böse, funktioniert aber unabhängig von der Größe der Listen:
quelle
Mehrere Einzeiler, inspiriert von Antworten auf eine andere Frage :
quelle
Wie wäre es mit Numpy? Es funktioniert auch mit Strings:
Ergebnis:
quelle
Eine funktionale und unveränderliche Alternative (Python 3):
quelle
Ich würde das Einfache tun:
Es wird ein Iterator erstellt, ohne dass zusätzlicher Speicherbedarf entsteht.
quelle
chain.from_iterable(izip(list1, list2), list1[len(list2):])
für das hier gestellte Problem beheben ... list1 soll das längere sein.Ich bin zu alt, um mit Listenverständnissen fertig zu werden, also:
quelle