2

I am just playing along with python to understand the things in more depth.

I learned that One of the easier ways is to use zip, but how about this:

>>> a = [[1,1,1], [2,2,2], [3,3,3]]
>>> for i in range(len(a)):
...   for j in range(len(a[0])):
...     a[i][j], a[j][i] = a[j][i], a[i][j]
... 
>>> a
[[1, 1, 1], [2, 2, 2], [3, 3, 3]]
>>> 

well, I was expecting the answer to be

[[1, 2, 3], [1, 2, 3], [1, 2, 3]]

because that is what Transpose would be ? I swapped the elements, right?? Also, this way was more natural to me. I read the documentation for zip here and it does not say anything about such "tricks". How to learn these more pythonic ways of doing the things? I am aware that asking for resources to learn goes into subjective choices and SO does not encourage such questions. But IMO, it is clearly not a matter of choice in this case, but finding any and every resource where such information is available.

Adorn
  • 1,403
  • 1
  • 23
  • 46
  • 3
    I don't get it. Is there a question here? – cs95 Dec 27 '17 at 17:49
  • Did you notice that your list doesn't end up transposed? – user2357112 Dec 27 '17 at 17:54
  • @cᴏʟᴅsᴘᴇᴇᴅ, edited question – Adorn Dec 27 '17 at 17:55
  • 2
    Unfortunately, you swap the same set of elements twice. So, you end up transposing, and then undoing what you did later on. – cs95 Dec 27 '17 at 17:58
  • @cᴏʟᴅsᴘᴇᴇᴅ, gotcha. Could you comment on second part? I would not want to write these two for loops when one liner is available. This way, by using as much internal functionality as possible, there would be less margin for silly mistakes I guess. – Adorn Dec 27 '17 at 18:03
  • I think default username guy did a pretty good job of explaining it. You basically iterate over the same pair of elements twice, doing, and undoing the same operation at different stages. The solution, as the answer shows, is to iterate over the upper triangular indices _only_! – cs95 Dec 27 '17 at 18:04
  • @cᴏʟᴅsᴘᴇᴇᴅ oh, i meant where to learn more pythonic ways of doing the things, like using `zip` for transposing – Adorn Dec 27 '17 at 18:06
  • I learned the easy way: By answering questions on Stack Overflow :-) – cs95 Dec 27 '17 at 18:07
  • Does this answer your question? [Transpose list of lists](https://stackoverflow.com/questions/6473679/transpose-list-of-lists) – Code-Apprentice Dec 11 '22 at 08:14

3 Answers3

11

You swap l[0][1] with l[1][0]... and then when you get to l[1][0], you swap l[1][0] with l[0][1]. Every pair of elements gets swapped twice, except for the diagonal elements, but those get swapped with themselves anyway. Everything ends up back where it started.

If you want to perform a transpose by element swaps, you need to avoid swapping pairs twice:

for i in range(len(a)):
    for j in range(i+1, len(a)):
        a[i][j], a[j][i] = a[j][i], a[i][j]

Also, your transpose implicitly assumes square input. If you get a 3x5 input, you can't swap a[2][4] with a[4][2], because there is no a[4][2].

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Great that you added a disclaimer about rectangular matrices. – cs95 Dec 27 '17 at 18:01
  • gotcha! any comment on second part of the question? where to learn more pythonic ways of doing the things, like using `zip` for transpose? My natural thought-process was to iterate and then swap. `zip` documentation does not cover it, hence i call it a "trick" – Adorn Dec 27 '17 at 18:08
  • @Adorn: [Google does a decent job](https://www.google.com/search?q=python+transpose), although you shouldn't automatically trust whatever comes up on Google. – user2357112 Dec 27 '17 at 18:10
  • @user2357112, yes it is true. But one would google if problem is unsolved or there is a mismatch between reality and expectation. I was more inclined to know book./videos./blogs. Googling every single sub-problem is not worth of time as it leads to different train of thoughts altogether, IMO – Adorn Dec 27 '17 at 18:20
  • @Adorn: Maybe those are the situations in which you'd google, but I suggest googling more. – user2357112 Dec 27 '17 at 18:37
1

You could also just use a basic list comprehension here:

a = [[1,1,1], [2,2,2], [3,3,3]]

transposed = [[x[i] for x in a] for i in range(len(a[0]))]

print(transposed)
# [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
0

The problem is that you are overwriting a during your loop, such that after the first transpose operation, the second just undoes the first.

You could either make a copy of a (and not overwrite a), or do it by a list comprehension.

import copy
a = [[1,1,1], [2,2,2], [3,3,3]]
a2  = copy.deepcopy(a)
for i in range(len(a)):
  for j in range(len(a[0])):
    a2[i][j] = a[j][i]

a3 = [[a[j][i] for j, _ in enumerate(ai)] for i, ai in enumerate(a)]

print(a)
print(a2)
print(a3)
Amos Egel
  • 937
  • 10
  • 24