Відповіді:
Як щодо
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()
, це рішення є тим, яке найбільше в дусі Пітона ...
просто для розваги, дійсні прямокутники та припускаючи, що 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Значення за замовчуванням - None
. Завдяки @ Jena в відповіді , де map()
змінюються внутрішні кортежі списків. Тут він перетворює ітератори на списки. Завдяки коментарям @ Oregano та @ badp .
У Python 3 передайте результат, list()
щоб отримати той самий двовимірний список, що і метод 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 працює з роздвоєними двовимірними списками, на відміну від першого коду, який використовує 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]
Можливо, не найелегантніше рішення, але ось рішення з використанням вкладених циклів:
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]]
.