0

I really don't understand the logic here.......

def transpose(A):
    output = [['']*len(A)] * len(A[0])
    for j in range(len(A[0])):
        for i in range(len(A)):
            output[j][i] = A[i][j]
    return output

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

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

My Output: [[3,6,9], [3,6,9], [3,6,9]]

I know I can use zip to solve this problem easily, but I just want to know why this code will return duplicated lists.

New update, I have added some print to understand the process

def transpose(A):
    output = [['']*len(A)] * len(A[0])
    for j in range(len(A[0])):
        for i in range(len(A)):
            output[j][i] = A[i][j]
            print(j)
            print(i)
            print(output)
    return output

And the outputs are:

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

So, for example, the very first step of the loop. j = 0 and i = 0. However, output[0][0],output[1][0],and output[2][0] are all changed by the loop. Why is that??????

I am so confused right now. I have written the same code in Java and it runs properly.

public class TransposeMatrix {
    public static int[][] transpose(int[][] A) {
        int[][] result = new int[A[0].length][A.length];
        for (int j = 0; j < A[0].length; j++) {
            for (int i = 0; i < A.length; i++) result[j][i] = A[i][j];
        }
        return result;
    }
}

The link of this problem is: https://leetcode.com/problems/transpose-matrix/

Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
Suckway
  • 11
  • 5
  • `transposed_matrix = list(map(list, zip(*input_matrix)))` input_matrix - list of lists; transposed_matrix - list of lists – bubble Apr 27 '19 at 04:32
  • Thanks for answering the question. I know use zip is easy as I mentioned in the question. But my problem is that I am confused by the logic behind the code that I provided. – Suckway Apr 27 '19 at 04:38
  • The `*` creates a number of references to the same list. – Klaus D. Apr 27 '19 at 04:40
  • This is due to [['']*len(A)] consist of the same list ; so, when you change one nested list, all lists are changed. This is behavior of multiplication `[]*N` and because lists are mutable in Python; Replace output with `[['' for k in A]] * len(A[0])`. – bubble Apr 27 '19 at 04:41
  • @KlausD. You are right! Thank you very much – Suckway Apr 27 '19 at 04:44
  • @bubble one more question, since I have used ['']*len(A), why that did not change anything? Do you mean that * only affects nested lists? – Suckway Apr 27 '19 at 04:49
  • Consider using `output = numpy.zeros((3,3))` to create your array, which gives you a 3x3 matrix will all 0 elements. Reference:https://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html – Devesh Kumar Singh Apr 27 '19 at 04:59

1 Answers1

1

When you multiply lists in python like that, you don't actually create new lists but several references to the same list. Thus, when you change the value in one list, you also change it in the other lists. That's why your output is [[3,6,9], [3,6,9], [3,6,9]]; it's simply the last of the three lists (i.e. from the last value of the for loop).

Instead, you can do this:

def transpose(A):
    output = [['']* (len(A)) for y in range(len(A[0]))]
    # or: output = [['' for x in range(len(A))] for y in range(len(A[0]))]
    for j in range(len(A[0])):
        for i in range(len(A)):
            output[j][i] = A[i][j]
    return output

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

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

Hope this helps!

Julian
  • 174
  • 8
  • You're welcome! This has confused me often. Also, beware when you want to copy a list you need to use `.copy()` instead of simply `list1 = list2` since the latter only creates a reference (see [link](https://www.programiz.com/python-programming/methods/list/copy)) – Julian Apr 27 '19 at 04:56