简体   繁体   中英

How to transpose a n-by-m matrix into a new m-by-n matrix using only loops?

The function transpose(a) should create a new matrix that is a transposition of the original one and return the new matrix to the caller.

This is one of my previous attempts, the one that makes the most sense to me if I am only to use loops...

def transpose(a):
    m = [None]*len(a[0])

    for i in range(len(a)):
        m[i] = [None]*len(a)
        for j in range(len(a[i])):
            m[i][j] = a[j][i]

    return m

I tried the code in the python shell with: transpose([[4,8,10,68],[5,12,8,71],[5.5,11,8,70.5]]) but got an "IndexError: list index out of range"

First, note that you do not have a matrix . Rather, you have a list of lists , which is one way of representing the mathematical abstraction of a matrix.

The problem with your code is just that you have the axes mixed up:

def transpose(a):
    m = [None] * len(a[0])
    for i in range(len(a[0])):  # len(a[0]) is the number of elements in the inner list, but after transposition it will be the number of elements in the outer list
        m[i] = [None] * len(a)
        for j in range(len(a)):  # and the other way round for len(a)
            m[i][j] = a[j][i]

    return m

That said, I suggest a different method. Using enumerate , we can refer to elements of a , as well as their indices , simultaneously:

def transpose(a):
    m = [None] * len(a)
    for i, sublist in enumerate(a):
        m[i] = [None] * len(sublist)
        for j, element in enumerate(sublist):
            m[i][j] = element

    return m

This maintains the spirit of your original answer, but is (IMO) cleaner.

A third way would be to dispense with creating lists filled with None and to use append instead:

def transpose(a):
    m = []
    for i, sublist in enumerate(a):
        m.append([])
        for j, element in enumerate(sublist):
            m[i].append(element)

    return m

Lastly, for completeness, a non-loop based approach (note that the inner elements are tuples instead of lists :

def transpose(a):
    return list(zip(*a))

Corrected version of your code:

def transpose(a):
    m = [None]*len(a[0])

    for i in range(len(a[0])):
        m[i] = [None]*len(a)
        for j in range(len(a)):
            m[i][j] = a[j][i]

    return m

Two small mistakes were made during the traversal of the array, the first loop was range(len(a)) but should be range(len(a[0])) as you want to go trough the 2d array column by column and the second mistake was range(len(a[i])) instead of range(len(a)) . You inverted the two axis during your traversal of the 2d array.

In python you don't need to allocate memory the way you are doing, as the underlying type is just a list of list, you can use the append method to add element.

You can try the following code that uses the notion of list comprehension.

def transpose(a):
  return [[a[x][i] for x in range(len(a))] for i in range(len(a[0]))]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM