Ответы:
Как насчет
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Для Python 3.x пользователи могут использовать
list(map(list, zip(*l)))
Объяснение:
Есть две вещи, которые мы должны знать, чтобы понять, что происходит:
zip(*iterables)
это означает, zip
что ожидается произвольное количество аргументов, каждый из которых должен быть итеративным. Например zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
будет вызываться так f
, чтобы каждый элемент args
был отдельным позиционным аргументомf
.Возвращаясь к входу из вопроса l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
будет эквивалентно zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. Остальное просто убедитесь, что результатом является список списков, а не список кортежей.
list(zip(*l))
работает правильно в Python 3.
zip(*l)
в Python 2), но вы получаете список кортежей, а не список списков. Конечно, list(list(it))
всегда одно и то же list(it)
.
Один из способов сделать это с помощью транспонирования NumPy. Для списка:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Или другой без почтового индекса:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
, что смогу это сделать Вот небольшое уточнение , которое не требует 2 вызова, хотя:map(lambda *a: list(a), *l)
map(None, ...)
не похоже на работу для Py3. Генератор создается , но next()
сразу же выдает ошибку: TypeError: 'NoneType' object is not callable
.
Эквивалентно решению Йены:
>>> 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]]
map()
, это решение является наиболее подходящим для духа Python ...
просто для удовольствия, действительные прямоугольники и предполагая, что m [0] существует
>>> 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]]
[[j[i] for j in l] for i in range(len(l[0]))]
. Конечно, вы должны быть уверены, что список l
не пуст.
Методы 1 и 2 работают в Python 2 или 3, и они работают на рваных, прямоугольных 2D-списками. Это означает, что внутренние списки не должны иметь одинаковую длину (рваные) или внешние списки (прямоугольные). Другие методы, ну, это сложно.
import itertools
import six
list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]
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()
становится
itertools.izip_longest()
в Python 2itertools.zip_longest()
в Python 3По умолчанию fillvalue есть None
. Благодаря ответу @ jena , где map()
происходит изменение внутренних кортежей в списки. Здесь он превращает итераторы в списки. Благодаря комментариям @ Oregano и @ badp .
В Python 3 передайте результат, list()
чтобы получить тот же 2D-список, что и в методе 2.
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, '-']]
@ InspectorG4dget альтернатива .
map()
из map()
- сломан в 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]]
Эта необычайно компактная вторая альтернатива @SiggyF работает с рваными 2D-списками, в отличие от его первого кода, который использует numpy для транспонирования и прохождения через рваные списки. Но None не должно быть значением заполнения. (Нет, None, передаваемый внутренней карте (), не является значением заполнения. Это означает, что нет функции для обработки каждого столбца. Столбцы просто передаются во внешнюю карту (), которая преобразует их из кортежей в списки.
Где-то в Python 3 map()
перестали мириться со всем этим злоупотреблением: первым параметром не может быть None, а рваные итераторы просто усекаются до самых коротких. Другие методы все еще работают, потому что это относится только к внутренней карте ().
map()
из map()
вновь>>> 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+
Увы, рваные строки НЕ становятся рваными столбцами в Python 3, они просто усекаются. Бу Ху прогресс.
solution1 = map(list, zip(*l))
solution2 = [list(i) for i in zip(*l)]
solution3 = []
for i in zip(*l):
solution3.append((list(i)))
print(*solution1)
print(*solution2)
print(*solution3)
# [1, 4, 7], [2, 5, 8], [3, 6, 9]
Возможно, не самое элегантное решение, но вот решение, использующее вложенные циклы while:
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
import numpy as np
r = list(map(list, np.transpose(l)))
more_itertools.unzip()
легко читается, и это также работает с генераторами.
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
или эквивалентно
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
Вот решение для транспонирования списка списков, который не обязательно квадратный:
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])
#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
l
размер не является равномерным (скажем, некоторые строки короче других),zip
он не компенсирует это и вместо этого отсекает строки из выходных данных. Такl=[[1,2],[3,4],[5]]
дает тебе[[1,3,5]]
.