Laten we nemen:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Het resultaat dat ik zoek is
r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
en niet
r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
Zeer gewaardeerd
Antwoord 1, autoriteit 100%
Wat dacht je van
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Voor python 3.x kunnen gebruikers
list(map(list, zip(*l))) # short circuits at shortest nested list if table is jagged
list(map(list, itertools.zip_longest(*l, fillvalue=None))) # discards no data if jagged and fills short nested lists with None
Uitleg:
Er zijn twee dingen die we moeten weten om te begrijpen wat er aan de hand is:
- De handtekening van zip:
zip(*iterables)
Dit betekent datzip
een willekeurig aantal argumenten verwacht die elk itereerbaar moeten zijn. bijv.zip([1, 2], [3, 4], [5, 6])
. - Uitgepakte argumentlijsten: gegeven een reeks van argumenten
args
,f(*args)
roeptf
aan zodat elk element inargs
een afzonderlijk positioneel argument is vanf
. itertools.zip_longest
verwijdert geen gegevens als het aantal elementen van de geneste lijsten niet hetzelfde (homogeen) is en vult in plaats daarvan de kortere geneste lijsten in daarnaritst ze dicht.
Terugkomend op de invoer van de vraag l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
zou gelijk zijn aan zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. De rest zorgt ervoor dat het resultaat een lijst met lijsten is in plaats van een lijst met tupels.
Antwoord 2, autoriteit 17%
Een manier om dit te doen is met NumPy transponeren. Voor een lijst, een:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Of een andere zonder ritssluiting:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Antwoord 3, autoriteit 16%
Equivalent aan Jena’s oplossing:
>>> 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]]
Antwoord 4, autoriteit 7%
gewoon voor de lol, geldige rechthoeken en ervan uitgaande dat m[0] bestaat
>>> 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]]
Antwoord 5, autoriteit 6%
Methoden 1 en 2 werken in Python 2 of 3, en ze werken op rafelige, rechthoekige2D-lijsten. Dat betekent dat de binnenlijsten niet dezelfde lengte hoeven te hebben als elkaar (rafelig) of als de buitenste lijsten (rechthoekig). De andere methoden, nou ja, het is ingewikkeld.
de installatie
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()
wordt
itertools.izip_longest()
in Python 2itertools.zip_longest()
in Python 3
De standaard vulwaarde is None
. Met dank aan @jena’s answer, waarbij map()
de binnenste tupels verandert in lijsten. Hier verandert het iterators in lijsten. Met dank aan de reactiesvan @Oregano en @badp.
Geef in Python 3 het resultaat door list()
om dezelfde 2D-lijst te krijgen als methode 2.
methode 2 — lijstbegrip, 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, '-']]
Het @inspectorG4dget alternatief.
methode 3 — map()
van map()
— gebroken 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]]
Dit buitengewoon compacte @SiggyF tweede alternatiefwerkt met rafelige 2D-lijsten, in tegenstelling tot zijn eerste code die numpy gebruikt om te transponeren en door gerafelde lijsten gaan. Maar Geen moet de vulwaarde zijn. (Nee, de Geen die is doorgegeven aan de binnenste map() is niet de vulwaarde. Het betekent dat er geen functie is om elke kolom te verwerken. De kolommen worden gewoon doorgegeven aan de buitenste kaart() die ze van tupels naar lijsten converteert.)
Ergens in Python 3, map()
hield op met al dit misbruik: de eerste parameter kan geen Geen zijn, en rafelige iterators worden gewoon afgekapt tot de kortste. De andere methoden werken nog steeds omdat dit alleen van toepassing is op de inner map().
methode 4 — map()
van map()
herzien
>>> 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+
Helaas worden de rafelige rijen GEEN rafelige kolommen in Python 3, ze worden gewoon afgekapt. Boehoe-voortgang.
Antwoord 6, autoriteit 2%
Drie opties om uit te kiezen:
1. Kaart met Zip
solution1 = map(list, zip(*l))
2. Lijstbegrip
solution2 = [list(i) for i in zip(*l)]
3. Voor lus toevoegen
solution3 = []
for i in zip(*l):
solution3.append((list(i)))
En om de resultaten te bekijken:
print(*solution1)
print(*solution2)
print(*solution3)
# [1, 4, 7], [2, 5, 8], [3, 6, 9]
Antwoord 7
import numpy as np
r = list(map(list, np.transpose(l)))
Antwoord 8
Misschien niet de meest elegante oplossing, maar hier is een oplossing met geneste while-lussen:
def transpose(lst):
newlist = []
i = 0
while i < len(lst):
j = 0
colvec = []
while j < len(lst):
colvec.append(lst[j][i])
j = j + 1
newlist.append(colvec)
i = i + 1
return newlist
Antwoord 9
more_itertools.unzip()
is gemakkelijk te lezen en werkt ook met generatoren.
import more_itertools
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
of gelijkwaardig
import more_itertools
l = more_itertools.chunked(range(1,10), 3)
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
Antwoord 10
matrix = [[1,2,3],
[1,2,3],
[1,2,3],
[1,2,3],
[1,2,3],
[1,2,3],
[1,2,3]]
rows = len(matrix)
cols = len(matrix[0])
transposed = []
while len(transposed) < cols:
transposed.append([])
while len(transposed[-1]) < rows:
transposed[-1].append(0)
for i in range(rows):
for j in range(cols):
transposed[j][i] = matrix[i][j]
for i in transposed:
print(i)
Antwoord 11
Nog een manier voor vierkante matrix. Geen numpy, noch itertools, gebruik (effectieve) uitwisseling van elementen ter plaatse.
def transpose(m):
for i in range(1, len(m)):
for j in range(i):
m[i][j], m[j][i] = m[j][i], m[i][j]
Antwoord 12
Hier is een oplossing voor het transponeren van een lijst met lijsten die niet noodzakelijk vierkant is:
maxCol = len(l[0])
for row in l:
rowLength = len(row)
if rowLength > maxCol:
maxCol = rowLength
lTrans = []
for colIndex in range(maxCol):
lTrans.append([])
for row in l:
if colIndex < len(row):
lTrans[colIndex].append(row[colIndex])
Antwoord 13
#Import functions from library
from numpy import size, array
#Transpose a 2D list
def transpose_list_2d(list_in_mat):
list_out_mat = []
array_in_mat = array(list_in_mat)
array_out_mat = array_in_mat.T
nb_lines = size(array_out_mat, 0)
for i_line_out in range(0, nb_lines):
array_out_line = array_out_mat[i_line_out]
list_out_line = list(array_out_line)
list_out_mat.append(list_out_line)
return list_out_mat