Question

I am trying to find a way to transpose a matrix, for example for:

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

it would change the matrix to:

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

So far, I tried several things but it never worked. I tried:

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

or

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

or

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

I want to code it without using external library such as numpy.

After that, it returns the result to this menu and use the transposed matrix for upcoming option (not shown):

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')
Was it helpful?

Solution

You aren't actually assigning the result of your manipulations, and therefore return the original matrix unchanged. For example:

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

Instead, try:

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

or simply:

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

Bear in mind that you will need to assign the return from the function in the calling function, too:

matrix = transpose_matrix(matrix)

In-place modification

Alternatively, you could transpose in-place and implicitly return None:

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

This way you don't have to assign back to matrix when you call the function.

Examples

Examples of the functions in action:

>>> 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 behaviour

It is important to note that zip will truncate its output to the shortest argument iterable, e.g.:

>>> 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)]
[]

Therefore if any of the rows of your matrix are empty lists, your output will be an empty list. You can use zip_longest from itertools to insert dummy fillvalues (None by default) instead:

>>> 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)]

You could implement this as:

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

with from itertools import zip_longest at the top of your script.

OTHER TIPS

There are some problems with the solutions you tried:

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

The result from zip(…) is thrown away, and you return the original matrix instead. Write return zip(*matrix).

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

Same as above, the result from map(…) is thrown away. Write return map(list, zip(*matrix)) instead.

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

The argument is named matrix, but you are working on m. So either rename the parameter m, or change the zipped value to *matrix.


Examples:

>>> 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]]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top