Câu trả lời:
Làm thế nào về
map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Đối với người dùng python 3.x có thể sử dụng
list(map(list, zip(*l)))
Giải trình:
Có hai điều chúng ta cần biết để hiểu chuyện gì đang xảy ra:
zip(*iterables)
Điều này có nghĩa là zip
mong đợi một số lượng đối số tùy ý mà mỗi đối số phải được lặp lại. Ví dụ zip([1, 2], [3, 4], [5, 6])
.args
, f(*args)
sẽ gọi f
sao cho mỗi phần tử trong args
là một đối số vị trí riêng biệt của f
.Quay trở lại đầu vào từ câu hỏi l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
, zip(*l)
sẽ tương đương với zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
. Phần còn lại chỉ là đảm bảo kết quả là một danh sách các danh sách thay vì một danh sách các bộ dữ liệu.
list(zip(*l))
hoạt động chính xác trong Python 3.
zip(*l)
trong Python 2), nhưng bạn nhận được một danh sách các bộ dữ liệu, không phải danh sách các danh sách. Tất nhiên, list(list(it))
luôn luôn là điều tương tự như list(it)
.
Một cách để làm điều đó là với chuyển đổi NumPy. Đối với một danh sách, một:
>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Hoặc một số khác không có zip:
>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map
có thể làm điều đó. Đây là một sàng lọc nhỏ không yêu cầu 2 cuộc gọi, mặc dù:map(lambda *a: list(a), *l)
map(None, ...)
dường như không hoạt động cho Py3. Trình tạo được tạo nhưng next()
gây ra lỗi ngay lập tức : TypeError: 'NoneType' object is not callable
.
Tương đương với giải pháp của 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]]
map()
, giải pháp này là giải pháp phù hợp nhất với tinh thần Python ...
chỉ để vui, hình chữ nhật hợp lệ và giả sử rằng m [0] tồn tại
>>> 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]))]
. Tất nhiên, bạn phải chắc chắn rằng danh sách đó l
không trống.
Phương thức 1 và 2 hoạt động trong Python 2 hoặc 3 và chúng hoạt động trên các danh sách 2D hình chữ nhật rách rưới . Điều đó có nghĩa là các danh sách bên trong không cần phải có cùng độ dài với nhau (rách rưới) hoặc như các danh sách bên ngoài (hình chữ nhật). Các phương pháp khác, tốt, nó phức tạp.
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()
trở thành
itertools.izip_longest()
trong Python 2itertools.zip_longest()
trong Python 3Giá trị mặc định là None
. Nhờ câu trả lời của @ jena , nơi map()
thay đổi các bộ dữ liệu bên trong thành danh sách. Ở đây nó đang biến các vòng lặp thành danh sách. Cảm ơn ý kiến của @ Oregano và @ badp .
Trong Python 3, chuyển kết quả qua list()
để có được danh sách 2D giống như phương thức 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, '-']]
Các @ inspectorG4dget thay thế .
map()
của map()
- bị hỏng trong 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]]
Giải pháp thay thế thứ hai @SiggyF cực kỳ nhỏ gọn này hoạt động với các danh sách 2D rách rưới, không giống như mã đầu tiên của anh ta sử dụng numpy để hoán vị và chuyển qua các danh sách rách rưới. Nhưng không có gì phải là giá trị điền. .
Ở đâu đó trong Python 3, map()
đã ngừng đưa ra tất cả sự lạm dụng này: tham số đầu tiên không thể là Không có, và các trình vòng lặp rách rưới chỉ bị cắt ngắn nhất. Các phương thức khác vẫn hoạt động vì điều này chỉ áp dụng cho bản đồ bên trong ().
map()
của map()
revisited>>> 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+
Than ôi, các hàng rách rưới KHÔNG trở thành các cột rách rưới trong Python 3, chúng chỉ bị cắt cụt. Boo hoo tiến bộ.
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]
Có thể không phải là giải pháp tao nhã nhất, nhưng đây là một giải pháp sử dụng các vòng lặp lồng nhau:
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()
rất dễ đọc, và nó cũng hoạt động với máy phát điện.
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
hoặc tương đương
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
Đây là một giải pháp để hoán chuyển danh sách các danh sách không nhất thiết phải là hình vuông:
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
không có kích thước đồng đều (giả sử, một số hàng ngắn hơn các hàng khác),zip
sẽ không bù cho nó và thay vào đó cắt đi các hàng khỏi đầu ra. Vì vậy,l=[[1,2],[3,4],[5]]
cung cấp cho bạn[[1,3,5]]
.