转换这个矩阵(python3)

-1 投票
2 回答
2420 浏览
提问于 2025-04-18 05:21

我正在寻找一种方法来转置一个矩阵,比如说:

[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]

这样就会把矩阵变成:

[[1, 4, 7],
 [2, 5, 8],
 [3, 6, 9]]

到目前为止,我尝试了几种方法,但都没有成功。我试过:

def transpose_matrix(matrix): # this one doesn't change the matrix at all
    zip(*matrix)
    return matrix  

或者

def transpose_matrix(matrix):
   map(list, zip(*matrix))
   return matrix

或者

 def transpose_matrix(matrix): # this one returns an empty list []
    print(list(zip(*matrix)))

我想自己编写代码,而不使用像 numpy 这样的外部库。

之后,它会把结果返回到这个菜单,并使用转置后的矩阵进行后续选项(未显示):

def menu(matrix):
    print('choose option')
    loop = True
    while loop:
        print('''
        1-display matrix
        7-transpose it
        8-other option
        0-back
        ''')
        choi = input('cchoice:')
        if choi =='1':
            print('\n'.join([' '.join(map(str, row)) for row in matrix]))

        elif choix == '7':
            matrix = transpose_matrix(matrix)

        else:
            print('invalid choice')

2 个回答

1

你尝试的解决方案有一些问题:

def transpose_matrix(matrix):
    zip(*matrix)
    return matrix

你用 zip(…) 得到的结果被丢掉了,你返回的是原来的矩阵。应该写成 return zip(*matrix)

def transpose_matrix(matrix):
   map(list, zip(*matrix))
   return matrix

和上面一样,map(…) 得到的结果也被丢掉了。应该写成 return map(list, zip(*matrix))

def transpose_matrix(matrix):
    print(list(zip(*m)))

参数叫 matrix,但你在用 m。所以要么把参数 m 改个名字,要么把压缩后的值改成 *matrix


示例:

>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*m))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> list(map(list, zip(*m)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2

你其实并没有真正“赋值”你所做的操作的结果,所以返回的还是原来的 matrix,没有改变。例如:

def transpose_matrix(matrix):
    zip(*matrix) # ignore result of computation
    return matrix # return argument unchanged 

相反,你可以试试:

def transpose_matrix(matrix):
    matrix = list(map(list, zip(*matrix))) # assign result 
    return matrix # return transposed matrix

或者简单地:

def transpose_matrix(matrix):
    return list(map(list, zip(*matrix)))

记住,你在调用这个函数的时候,也需要把返回的结果赋值给调用的函数:

matrix = transpose_matrix(matrix)

就地修改

另外,你可以选择就地转置,并隐式地 return None

def transpose_matrix(matrix):
    matrix[:] = list(map(list, zip(*matrix)))

这样在调用函数的时候,你就不需要再把结果赋值回 matrix 了。

示例

下面是这些函数实际运行的例子:

>>> def transpose_matrix(matrix):
    return list(map(list, zip(*matrix)))

>>> transpose_matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> def in_place_transpose(matrix):
    matrix[:] = list(map(list, zip(*matrix)))


>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> in_place_transpose(m)
>>> m
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

zip 的行为

需要注意的是,zip 会把输出截断到最短的参数可迭代对象,比如:

>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8]
>>> d = [9]
>>> e = []
>>> for l in (b, c, d, e):
    print(list(zip(a, l)))


[(1, 4), (2, 5), (3, 6)]
[(1, 7), (2, 8)]
[(1, 9)]
[]

所以如果你的 matrix 中有任何一行是空列表,输出就会是一个空列表。你可以使用 zip_longest 来自 itertools 来插入虚拟的 fillvalue(默认是 None):

>>> from itertools import zip_longest
>>> list(zip_longest([1, 2, 3], [4, 5]))
[(1, 4), (2, 5), (3, None)]
>>> m = [[1, 2, 3], [4, 5, 6], []]
>>> list(zip_longest(*m, fillvalue=0))
[(1, 4, 0), (2, 5, 0), (3, 6, 0)]

你可以这样实现:

def transpose_matrix(matrix):
    return list(map(list, zip_longest(*matrix, fillvalue=0)))

在你的脚本顶部加上 from itertools import zip_longest

撰写回答