385 Stimmen

Liste von Listen transponieren

Nehmen wir an:

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Das Ergebnis, das ich suche, ist

r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

und nicht

r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

547voto

jena Punkte 7357

Python 3:

# short circuits at shortest nested list if table is jagged:
list(map(list, zip(*l)))

# discards no data if jagged and fills short nested lists with None
list(map(list, itertools.zip_longest(*l, fillvalue=None)))

Python 2:

map(list, zip(*l))

[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Erläuterung:

Es gibt zwei Dinge, die wir wissen müssen, um zu verstehen, was hier vor sich geht:

  1. Die Unterschrift von zip : zip(*iterables) Dies bedeutet zip erwartet eine beliebige Anzahl von Argumenten, von denen jedes iterierbar sein muss. z.B. zip([1, 2], [3, 4], [5, 6]) .
  2. Ungepackte Argumentationslisten : Bei einer Folge von Argumenten args , f(*args) wird anrufen f so dass jedes Element in args ist ein separates Positionsargument von f .
  3. itertools.zip_longest verwirft keine Daten, wenn die Anzahl der Elemente der verschachtelten Listen nicht gleich ist (homogen), und füllt stattdessen die kürzeren verschachtelten Listen aus entonces macht sie zu.

Um auf den Input aus der Frage zurückzukommen l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] , zip(*l) wäre gleichbedeutend mit zip([1, 2, 3], [4, 5, 6], [7, 8, 9]) . Der Rest besteht darin, sicherzustellen, dass das Ergebnis eine Liste von Listen und nicht eine Liste von Tupeln ist.

109voto

inspectorG4dget Punkte 103745

Dies entspricht der Lösung von Jena:

>>> l=[[1,2,3],[4,5,6],[7,8,9]]
>>> [list(i) for i in zip(*l)]
... [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

85voto

SiggyF Punkte 20140

Eine Möglichkeit, dies zu tun, ist mit NumPy transponieren . Für eine Liste, a:

>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Oder eine andere ohne Reißverschluss:

>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

29voto

matchew Punkte 18232

Nur zum Spaß, gültige Rechtecke und unter der Annahme, dass m[0] existiert

>>> m = [[1,2,3],[4,5,6],[7,8,9]]
>>> [[row[i] for row in m] for i in range(len(m[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

28voto

Bob Stein Punkte 14259

Die Methoden 1 und 2 funktionieren in Python 2 oder 3, und sie funktionieren auf zerklüftet, rechteckig 2D-Listen. Das bedeutet, dass die inneren Listen nicht die gleiche Länge haben müssen wie die äußeren Listen (rechteckig) oder wie die inneren Listen untereinander (zackig). Die anderen Methoden, nun ja, es ist kompliziert.

die Einrichtung

import itertools
import six

list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]

Methode 1 - map() , zip_longest()

>>> list(map(list, six.moves.zip_longest(*list_list, fillvalue='-')))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]

six.moves.zip_longest() wird

Der Standardfüllwert ist None . Dank @jena's Antwort donde map() ist die Umwandlung der inneren Tupel in Listen. Hier werden Iteratoren in Listen umgewandelt. Dank @Oregano's und @badp's Kommentare .

In Python 3 übergeben Sie das Ergebnis durch list() um die gleiche 2D-Liste wie bei Methode 2 zu erhalten.


Methode 2 - Verstehen von Listen, zip_longest()

>>> [list(row) for row in six.moves.zip_longest(*list_list, fillvalue='-')]
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]

En @inspectorG4dget alternativ .


Methode 3 - map() de map() - gebrochen in Python 3.6

>>> map(list, map(None, *list_list))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]]

Diese außerordentlich kompakte @SiggyF zweite Alternative funktioniert mit zackigen 2D-Listen, im Gegensatz zu seinem ersten Code, der Numpy zum Transponieren und Durchlaufen von zackigen Listen verwendet. Aber None muss der Füllwert sein. (Nein, das an die innere map() übergebene None ist nicht der Füllwert. Es bedeutet, dass es keine Funktion gibt, die jede Spalte verarbeitet. Die Spalten werden einfach an die äußere map() weitergegeben, die sie von Tupeln in Listen umwandelt).

Irgendwo in Python 3, map() hat aufgehört, diesen Missbrauch zu dulden: Der erste Parameter kann nicht None sein, und die lückenhaften Iteratoren werden einfach auf den kürzesten Wert gekürzt. Die anderen Methoden funktionieren weiterhin, da dies nur für die innere map() gilt.


Methode 4 - map() de map() überarbeitet

>>> list(map(list, map(lambda *args: args, *list_list)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]   // Python 2.7
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]] // 3.6+

Leider werden die ausgefransten Zeilen in Python 3 NICHT zu ausgefransten Spalten, sie werden nur abgeschnitten. Boo hoo Fortschritt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X