มาดูกัน:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ผลลัพธ์ที่ฉันต้องการคือ
r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
และไม่
r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
ชื่นชมมาก
มาดูกัน:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ผลลัพธ์ที่ฉันต้องการคือ
r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
และไม่
r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
ชื่นชมมาก
คำตอบ:
เกี่ยวกับ
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) แต่คุณจะได้รับรายชื่อของ tuples ไม่ใช่รายการของรายการ แน่นอนอยู่เสมอเป็นสิ่งเดียวกับlist(list(it))
list(it)
วิธีหนึ่งที่จะทำได้คือใช้ NumPy transpose สำหรับรายการ a:
>>> 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
.
เท่ากับโซลูชันของ 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()
แก้ปัญหานี้เป็นอย่างใดอย่างหนึ่งซึ่งเป็นส่วนใหญ่ในจิตวิญญาณของงูหลาม ...
เพียงเพื่อความสนุกสี่เหลี่ยมที่ถูกต้องและสมมติว่า 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 3fillvalue None
เริ่มต้นคือ ขอบคุณคำตอบของ @ jena ที่map()
เปลี่ยนทูเปิลภายในเป็นรายการ ที่นี่จะเปลี่ยน iterators เป็นรายการ ขอขอบคุณที่ @ @ และ 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 เพื่อโอนย้ายและส่งผ่านรายการที่ขาด แต่ไม่มีต้องเป็นค่าการเติม (ไม่, ไม่มีส่งผ่านไปยังแผนที่ด้านใน () ไม่ใช่ค่าการเติมซึ่งหมายความว่าไม่มีฟังก์ชั่นในการประมวลผลแต่ละคอลัมน์คอลัมน์เพิ่งผ่านไปยังแผนที่ด้านนอก () ซึ่งแปลงพวกมันจาก tuples เป็นรายการ
อยู่ที่ไหนสักแห่งใน 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 พวกมันจะถูกตัดทอน Boo Hoo คืบหน้าไป
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]]