Verknüpfen von Listen: Reißverschluss

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
achilles_69
User
Beiträge: 21
Registriert: Dienstag 31. März 2009, 14:05
Wohnort: Bielefeld

Hallo,

ich suche nach einer eleganten Lösung für folgendes Problem: ich habe zwei Listen und möchte die wie die beiden Hälften eines Reißverschlusses verbinden, also so

Code: Alles auswählen

list1 = ['a0', 'a1', 'a2']
list2 = ['b0', 'b1', 'b2']
dies soll also die folgende Liste ergeben:

Code: Alles auswählen

['a0', 'b0', 'a1', 'b1', 'a2', 'b2']
In meinem speziellen Fall ist sichergestellt, dass beide Listen die gleiche Anzahl von Elementen haben.
Zu einer primitiven quick'n'dirty-Version habe ich irgendwie keine Lust. Es gibt doch bestimmt eine elegante 'pythonische' Art einer Lösung...
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Code: Alles auswählen

In [71]: list(sum(zip(list1, list2), ()))
Out[71]: ['a0', 'b0', 'a1', 'b1', 'a2', 'b2']
:wink:
yipyip
achilles_69
User
Beiträge: 21
Registriert: Dienstag 31. März 2009, 14:05
Wohnort: Bielefeld

Super, funktioniert. Ich liebe solche Einzeiler...

Auf zip() war ich auch schon gestoßen, aber die erzeugt mir ja eine Liste von Sets.
Auf das sum() war ich nicht gekommen, ich verstehe im Moment aber noch nicht ganz, wie sum() in diesem Zusammenhang eigentlich genau funktioniert...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Persönlich bevorzuge ich ja diese Variante:

Code: Alles auswählen

from itertools import izip, chain
list(chain.from_iterable(izip(list1, list2)))
(Vermute auch, dass sie effizienter ist)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

zip erzeugt eine Liste von Tupeln, nicht von sets.

sum summiert mit optionalem Startwert:

Code: Alles auswählen

In [97]: sum((1, 2, 3), 10)
Out[97]: 16

In [98]: sum([[1, 2, 3]], [4, 5])
Out[98]: [4, 5, 1, 2, 3]

In [99]: sum(((1, 2, 3),(4, 5)), ())
Out[99]: (1, 2, 3, 4, 5)
Listen und Tupel werden damit verkettet.

@Leonidas:
Ich nehme auch an, das die Itertools effizienter sind, aber das andere erschien mir erstmal naheliegender. (... und vertrauter...)

:wink:
yipyip
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

yipyip hat geschrieben:Ich nehme auch an, das die Itertools effizienter sind, aber das andere erschien mir erstmal naheliegender. (... und vertrauter...)
Naja, der ``zip``/``izip``-Schritt ist in beiden Codes gleich (nur nutze ich ``izip``, weil ich keine resultierende Liste brauche, ein Iterable wie etwa ein Generator reicht auch. Du könntest auch ``izip`` nehmen, da ``sum`` damit auch zurechtkommt). Danach hat man dann eine Sequenz von 2-Tupeln. Darauf wende ich ``chain.from_iterable`` an, was einfach aus verschachtelten Iterables "flache" Iterables macht. Der letzte Schritt, dass ``list`` ist wieder gleich (nur wandelst du ein Tupel um und ich einen Generator).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Ich kannte zwar 'chain', aber nicht 'chain.from_iterable', das war der Knackpunkt. Jetzt werde ich's mir merken...

:wink:
yipyip
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

yipyip hat geschrieben:Ich kannte zwar 'chain', aber nicht 'chain.from_iterable', das war der Knackpunkt.
Ja, das ist ganz neu in Python 2.6. Wie immer: wenns das nicht gäbe, müsste es erfunden werden. :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Leonidas hat geschrieben:
yipyip hat geschrieben:Ich kannte zwar 'chain', aber nicht 'chain.from_iterable', das war der Knackpunkt.
Ja, das ist ganz neu in Python 2.6. Wie immer: wenns das nicht gäbe, müsste es erfunden werden. :)
Oder so:

Code: Alles auswählen

from itertools import izip, chain
list(chain(*izip(list1, list2)))
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

jbs hat geschrieben:Oder so:

Code: Alles auswählen

from itertools import izip, chain
list(chain(*izip(list1, list2)))
der * (Stern) vor izip bedeutet dass eine nicht festgelegte Anzahl von Parametern übergeben werden?
the more they change the more they stay the same
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Code: Alles auswählen

def func(*args, **kwargs):
    print args,
    print kwargs

func(1,2,3,a=4,b=5)
func(*(1,2,3), **{'a':4,'b':5})
http://docs.python.org/dev/library/iter ... ools.chain
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ah, danke, dass mit:

Code: Alles auswählen

func(*(1,2,3), **{'a':4,'b':5})
kannte ich gar nicht nur:

Code: Alles auswählen

func(1,2,3,a=4,b=5)
the more they change the more they stay the same
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dav1d hat geschrieben:der * (Stern) vor izip bedeutet dass eine nicht festgelegte Anzahl von Parametern übergeben werden?
Jein. Bei einem Aufruf "entpackt" ein ``*`` das folgende iterable zu mehreren Argumenten, in einer Funktionsdefinition erlaubt es beliebig viele Argumente.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also quasi das was in anderen Sprachen (und früher auch in Python) ``apply()`` gemacht hat (die Syntax mit dem Stern erinnert mich etwas an ``unquote-splicing`` in Scheme, was ähnlich funktioniert)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten