The code is supposed to make a copy of the original array and rotate it (turn the columns into rows) while keeping the original array the same but the original array changes without a reason.
This is most likely a deep copy issue but I have tried using copy.copy() and it has not worked
Code:
l = [[1,2,3],[4,5,6],[7,8,9]]
def rotate(funcl):
funcl = funcl[::-1]
for s1 in range(0, len(funcl)):
for s2 in range(s1, len(funcl)):
funcl[s1][s2], funcl[s2][s1] = funcl[s2][s1], funcl[s1][s2]
return funcl
print("Original Array:\n", l)
nextl = rotate(l)
print("Original Array after Function:\n", l)
print("New Rotated Array:\n", nextl)
Output:
Original Array:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Original Array after Function:
[[9, 6, 3], [8, 5, 2], [7, 4, 1]]
New Rotated Array:
[[7, 4, 1], [8, 5, 2], [9, 6, 3]]
As you can see the function works fine but changes the original array
CodePudding user response:
One way is to do a deepcopy with copy.deepcopy() before passing it to the function so every levels and nested sublevels of your list are duplicated:
import copy
l = [[1,2,3],[4,5,6],[7,8,9]]
def rotate(funcl):
funcl = funcl[::-1]
for s1 in range(0, len(funcl)):
for s2 in range(s1, len(funcl)):
funcl[s1][s2], funcl[s2][s1] = funcl[s2][s1], funcl[s1][s2]
return funcl
print("Original Array:\n", l)
nextl = rotate(copy.deepcopy(l))
print("Original Array after Function:\n", l)
print("New Rotated Array:\n", nextl)
output is:
Original Array:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Original Array after Function:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
New Rotated Array:
[[7, 4, 1], [8, 5, 2], [9, 6, 3]]
CodePudding user response:
deepcopy is notoriously slow and should be avoided if you can.
zip() is frequently used to transpose lists in python. Here the only wrinkle is that you want to reverse them. You can use reversed() for this and get a very succinct:
l = [[1,2,3],[4,5,6],[7,8,9]]
def rotate(funcl):
return list(zip(*reversed(funcl)))
print("Original Array:\n", l)
nextl = rotate(l)
print("Original Array after Function:\n", l)
print("New Rotated Array:\n", nextl)
Which prints:
Original Array:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Original Array after Function:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
New Rotated Array:
[(7, 4, 1), (8, 5, 2), (9, 6, 3)]
If it's important to maintain inner lists rather than tuples, you can add a map to mix:
l = [[1,2,3],[4,5,6],[7,8,9]]
def rotate(funcl):
return list(map(list, zip(*reversed(funcl))))
# or return [list(t) for t in zip(*reversed(funcl))]
rotate(l)
# [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
CodePudding user response:
Here's a version that works (plus a nicer way to print these lists):
def printlst(arr):
for row in arr:
print(*row)
def rotate(funcl):
newl = [row.copy() for row in funcl]
newl = newl[::-1]
for s1 in range(0, len(newl)):
for s2 in range(s1, len(newl)):
newl[s1][s2], newl[s2][s1] = newl[s2][s1], newl[s1][s2]
return newl
l = [[1,2,3],[4,5,6],[7,8,9]]
print("Original Array:")
printlst(l)
nextl = rotate(l)
print("Original Array after Function:")
printlst(l)
print("New Rotated Array:")
printlst(nextl)
The resulting output:
Original Array:
1 2 3
4 5 6
7 8 9
Original Array after Function:
1 2 3
4 5 6
7 8 9
New Rotated Array:
7 4 1
8 5 2
9 6 3
An alternative approach:
def rotate(funcl):
return [[funcl[j][i] for j in range(len(funcl))[::-1]] for i in range(len(funcl))]
CodePudding user response:
This is indeed a deep copy issue: funcl = funcl[::-1] only does a shallow copy.
Anyway the Pythonic way would be to directly build the tranposed array with a double list comprehension avoiding a copy followed with a rotation :
def rotate(funcl):
return [[funcl[j][i] for j in range(len(funcl))] for i in range(len(funcl))]
