Seite 1 von 1

verschachtelte Listen "verdrehen"?

Verfasst: Mittwoch 7. Mai 2008, 11:45
von martin86_mu
Hi,

ich möchte folgende Operation auf eine Liste der Länge x , die jeweils als Elemente wieder Listen der Länge y besitzt andwenden:

liste1 = [ [ A1, A2, A3] , [ B1, B2, B3] ]

--> liste2 = [ [A1, B1], [A2, B2], [A3, B3] ]

Ich bekomm leider keine saubere Lösung hin, hab aber noch ein Problem:
ich weiss irgendwie nicht genau, wie ich mein problem mit "fachbegriffen" beschreiben kann damit ich danach erfolgreich suchen kann (deshalb vielleicht auch ein etwas verwirrender Titel). Ich meine, dass ich dieses Problem schon mal hier im Forum gelesen habe, find aber keinen post.

Ich hoffe jemand kann mir helfen, gruß

Martin

Verfasst: Mittwoch 7. Mai 2008, 11:52
von CM

Code: Alles auswählen

[[x, y] for x, y in zip(liste1[0], liste1[1])]
Wenn es auch tuple sein dürfen:

Code: Alles auswählen

zip(liste1[0], liste1[1])
HTH
Christian

Verfasst: Mittwoch 7. Mai 2008, 11:58
von Masaru
Und händisch:

Code: Alles auswählen

def assert_equal(a,b):
    assert a == b, "%s != %s" % (a,b)

liste1 = [["a1", "a2",  "a3"], ["b1", "b2", "b3"]]
liste2 = []

# nochmal pruefen, ob 'liste1' auch soweit korrekt ist
# kann man natürlich auch in der nachfolgenden for-schleife integrieren,
# oder ganz weglassen, wenn man seiner Basis-Liste traut :D
[ assert_equal(len(elem), len(liste1[0])) for elem in liste1 ]

# nun die Kreuzverknüpfung an sich
for index in range(len(liste1[0])):
    liste2.append([ elem[index] for elem in liste1])
Das Resultat sah dann wie folgt aus:

Code: Alles auswählen

>>> print liste2
[['a1', 'b1'], ['a2', 'b2'], ['a3', 'b3']]
Sicher, nicht so kurz, bündig und performant wie CM's Variante, aber es tut's auch ;).

>>Masaru<<

Verfasst: Mittwoch 7. Mai 2008, 12:09
von martin86_mu
Hi, vielen dank an euch beide. Ich werd wohl den ' zip ' Befehl benutzen in Verbindung mit der (für meine Zwecke) sehr nützlichen Methode assert_equal. gruß [/quote]

Verfasst: Mittwoch 7. Mai 2008, 12:17
von Masaru
Eins dann aber noch ... die "zip"-Variante, funktioniert in der Form nur bei einer Liste "liste1", wenn diese auch genau zwei Unterlisten hat.

Bei drei Unterlisten funxt die Kreuzung leider schon nicht mehr:

Code: Alles auswählen

>>> liste1 = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']]
>>> liste2 = [[x, y] for x, y in zip(liste1[0], liste1[1])]
>>> print liste2
[['a1', 'b1'], ['a2', 'b2'], ['a3', 'b3']] # :(
Da ist die For-Schleife mit dem Index-Geraffel einiges flexibler ;):

Code: Alles auswählen

>>> liste1 = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']]
>>> liste2 = []
>>> for index in range(len(liste1[0])):
... 	liste2.append([ elem[index] for elem in liste1])
... 	
>>> print liste2
[['a1', 'b1', 'c1'], ['a2', 'b2', 'c2'], ['a3', 'b3', 'c3']] # :)

Verfasst: Mittwoch 7. Mai 2008, 12:20
von BlackJack
@martin86_mu: In der Mathematik ist für das vertauschen von Zeilen und Spalten einer Matrix der Begriff "transponieren" üblich.

Man kann auch diesen netten "Trick" anwenden:

Code: Alles auswählen

In [3]: liste
Out[3]: [['A1', 'A2', 'A3'], ['B1', 'B2', 'B3']]

In [4]: zip(*liste)
Out[4]: [('A1', 'B1'), ('A2', 'B2'), ('A3', 'B3')]

In [5]: map(list, zip(*liste))
Out[5]: [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3']]

Verfasst: Mittwoch 7. Mai 2008, 12:42
von Masaru
... funktioniert folglich auch mit beliebiger Anzahl an inneren Listen :).

Verfasst: Mittwoch 7. Mai 2008, 15:07
von martin86_mu
@Blackjack Ah ok danke irgendwie hab ich die Analogie von verschachtelten Listen zu Matrizen zuvor nicht wirklich realisiert. Thx

Verfasst: Mittwoch 7. Mai 2008, 16:29
von CM
Wenn es um Methoden geht, die eine "echte" Matrix betreffen, kannst Du auch auf numpy ausweichen. Dort ist das und viel mehr bereits implementiert.

edit: Dummen Rechtschreibfehler korrigiert.