need help understanding how python arrays work [duplicate] - python

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed last year.
So I'm trying to create an array visualiser with pygame and have run into a strange problem I can't seem to get around,
here's a small portion of code to recreate the issue
def appendto(array):
temp=[]
for i in range(3):
array.append(i)
temp.append(array)
return temp
array=[]
print(appendto(array))
When I run this code it shows
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
I am trying to make the temp array record each change made to the main array, but by the end it seems to have only recorded the final state of the array 3 times.
The only half - solution I have found is to turn the array into a string before appending it, doing
array.append(str(i))
but this will slow down my program significantly as I will then have to turn the string back into an array in order to use it.
please do tell me if I'm doing something wrong

I think adding a print() statement in your for loop might help illustrate what is going on.
def appendto(array):
temp=[]
for i in range(3):
array.append(i)
temp.append(array)
print(temp)
return temp
array=[]
print(appendto(array))
This will give you:
[[0]]
[[0, 1], [0, 1]]
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
We can see that appending items to array cascades though all references to array. To be clear, there is only one array we just now have a list of three items all pointing to it.
What you probably want to do is append a copy.
def appendto(array):
temp=[]
for i in range(3):
array.append(i)
temp.append(array.copy())
return temp
array=[]
print(appendto(array))
giving you:
[[0], [0, 1], [0, 1, 2]]

Related

2 Different 2d list with different locations, list 1 changes when list 2 is changed

I have 2 lists, grid and oldgrid. grid is a 3*3 list, and i assigned oldgrid as oldgrid = grid[:] as i know this should prevent this sort of issue.
Later in the code, i change an item in the list grid, but when i did this both grid and oldgrid changed. The code i have is
print(oldgrid)
print(id(oldgrid),id(grid))
grid[1][1] = 2
print(oldgrid)
which outputs
[[2, 1, 1], [1, 1, 0], [0, 1, 1]]
(139716659684608, 139716659609184)
[[2, 1, 1], [1,2, 0], [0, 1, 1]]
Both lists clearly have different locations in storage, (as shown by the print id statement) so how come when grid changes oldgrid changes as well?
Edit: Thanks for the solution, copy.deepcopy() works well.
The oldgrid = grid[:] copies the outer list, but in it, it keeps the inner lists
You need a deep copy
oldgrid = copy.deepcopy(grid)

Problem with appending with ndarray and lists. I solved it but couldn't get it as I want

Scenario: I have a function myfunction() that produces a ndarray always of the form [[0, 5]]. I call myfunction() three times (say) and each time I append the output to an array called nos_indices. It is shown below.
nos_indices=myfunction(some argument) #I call once like this first
for loop:
nos_indices.append( myfunction(some argument))
def myfunction(the argument):
....
ranges_ndarray = np.where(absdiff == 1)[0].reshape(-1, 2) #this gives [[0, 5]]
Problem: But when I call three times, the append does this [[0, 5], [[0, 5]], [[0, 5]]] It will be extremely difficult for me later to do indexing with this kind of structure.
My soln. to problem: So, I added this line ranges=ranges_ndarray.tolist() after ranges_ndarray
My soln. works lil but not how I want: Now, the function returns [0, 5] which is good. But just in 2 time calling I see that the append is doing like [0, 5, [0, 5]]. This is also wrong for me as I want the output after append to be like [[0, 5], [0, 5], ...]
Can anyone suggest how to deal with this and get the output like [[0, 5], [0, 5], ...] . I am out of idea on how to simultaneously deal with myfunction and the append output to produce the form I want.
I found out what was going wrong with this. My first call to the myfunction was nos_indices=myfunction(some argument) and then a for loop that keeps appending to this nos_indices. So, the first call gives [0, 5] which is ok but when called second time using the nos_indices.append( myfunction(some argument)), it caused to output to be [0, 5, [0, 5]]. Hence, to get [[0, 5], [0, 5], ...] I changed the first call as below.
nos_indices=myfunction(some argument) #THIS IS REPLACED BY NEXT TWO LINES
nos_indices=[]
nos_indices.append(myfunction(some argument))
#then the for loop and subsequent append code as in question
This change keeps the first [0, 5] intact even after second call and corresponding append thus giving me [[0, 5], [0, 5]]

Weird list append bug in Python? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
How to deep copy a list?
(10 answers)
How to get all subsets of a set? (powerset)
(32 answers)
Closed 1 year ago.
I'm trying to write a function in python that returns the powerset of a list inputted to it. In lines 5 and 6, I try to append an element to only the second half of the array but it apparently gets appended to all the elements of the array. Why does this happen and how can I fix it?
Code:
def powerset(array):
ans=[[]]
for elem in array:
ans.extend(ans.copy())
for j in range(int(len(ans)/2), len(ans)):
ans[j].append(elem)
return ans
Example input: [0, 1]
Output returned by above function: [[0, 1, 1], [0, 1, 1], [0, 1, 1], [0, 1, 1]]
Expected Output: [[], [0], [1], [0, 1]]
You're making a shallow copy of ans, means the elements inside the list in ans are not copied, they remain the same.
Use copy.deepcopy().
from copy import deepcopy
def powerset(array):
ans=[[]]
for elem in array:
ans.extend(deepcopy(ans))
for j in range(int(len(ans)/2), len(ans)):
ans[j].append(elem)
return ans
print(powerset([0, 1]))
Output:
[[], [0], [1], [0, 1]]

Comparing index positions of sublists in Python

I'm trying to understand what I'm missing in these two different methods. In the code below, I'm defining a list of lists, and calling it two ways. The first way is to call it in a print statement as one line, separating the index positions of the lists with commas, the second is to print them all separately.
list_of_lists = [[2, 2, 0], [2, 1, 0], [2, 1, 1]]
print(list_of_lists[0][0],[1][0],[2][0])
print('\n')
The output of this code is 2,1,2
print(winner_is_2[0][0])
print(winner_is_2[1][0])
print(winner_is_2[2][0])
The output of this code is 2,2,2
Why, in the first case, does the call output the wrong value for the second set of index positions?
The use case here is trying to check if a set of index positions in a list of lists is all equal to the same value (like you'd see in tic-tac-toe where you'd check if all the values in row x or column y are the same)
NOTE: I know I can use list extraction to get all the values at X position in these sublists, but I'd rather not use that method if possible.
In this snippet here:
list_of_lists = [[2, 2, 0], [2, 1, 0], [2, 1, 1]]
print(list_of_lists[0][0],[1][0],[2][0])
print('\n')
This is actually equivalent to:
list_of_lists = [[2, 2, 0], [2, 1, 0], [2, 1, 1]]
print(list_of_lists[0][0])
print([1][0])
print([2][0])
Python is interpreting the comma separated inputs as separate arrays [1] and [2] indexed by their first value [1][0] and [2][0] which leads to them being printed as 1,2
To see further evidence of this, try changing the values of 1 and 2 and seeing what you get by doing:
list_of_lists = [[2, 2, 0], [2, 1, 0], [2, 1, 1]]
print(list_of_lists[0][0],[5555][0],[262626][0])
print('\n')
Here you should get (2, 5555, 262626)
list_of_lists = [[2, 2, 0], [2, 1, 0], [2, 1, 1]]
print(list_of_lists[0][0], list_of_lists[1][0], list_of_lists[2][0])
print('\n')
Whats wrong with this?
What you trying is equivalent to:
print(list_of_lists[0][0], 1, 2)
So after a little more digging, thanks to Spencer Bard for explaining the syntax mistake, I was able to come up with code that works for precisely what I was trying to do. As I'm attempting to test a marker against each item at specific index positions within a list, the code that worked for me was as follows.
def win_check(marker_list,mark):
if (marker_list[0][0] == mark and marker_list[1][0] == mark and marker_list[2][0] == mark):
print(f'Winner is player {mark}!')
There are a lot more elif statements underneath that to account for the rest of the possibilities, but this is the general format.

List Malfunction? (Python)

I'm having problems with my lists.
Obviously, I have just missed something. :P
Can someone tell me what is going wrong here and how to fix it?
Here is where I am having the malfunction:
On = [0, 0, [[0, 0],[0,1]]]
tempList = []
tempList.append(On[2])
print(tempList)
tempList.append([On[0],On[1]+1])
print(tempList)
Just in case this is important, it is for my AI pathfinding.
The First Print:
[[[[0, 0]], [0, 1]]]
I wanted:
[[0,0],[0,1]]
The Second Print:
[[[[0, 0]], [0, 1]], [0, 2]]
I wanted:
[[0,0],[0,1],[0,2]]
On[2] is supposed to track my past movements.
I was trying to get my past movements (On[2]) to combine with the current movement.
I want the tempList to be like this:
[[0,1],[0,2],[0,3]]
But instead I get this:
[[[0,1],[0,2]],[0,3]]
On is stored in this format(Or supposed to be): [CurrentX,CurrentY,[[Step1X,Step1Y],[Step2X,Step2Y]] etc.
If you need any more info, just tell me what you need.
EDIT: The problem is whith the On and the tempList.
EDIT2: If you people need to, I can post all of the code so you can run it. :/
This line:
tempList.append([On[0],On[1]+1])
appends a list to the list. You want this:
tempList.extend([On[0], On[1] + 1])
On = [0, 1, [[0, 0],[0,1]]]
tempList = []
tempList.extend(On[2])
print(tempList)
tempList.append([On[0],On[1]+1]) # changing only this line
print(tempList)
...yields...
[[0, 0], [0, 1]]
[[0, 0], [0, 1], [0, 2]]
...which is the stated desired result.
If your Bottom comes out as...
[0, 0, [[[0,1],[0,2],[0,3]]]]
...when you want it to be...
[0, 0, [[0,1],[0,2],[0,3]]]
...then the problem may not be with tempList and its construction at all, but with the append call, which appends its argument as a single element.
That is to say:
a=[1,2]
b=[3]
a.append(b)
...results in...
a == [1,2,[3]]
...rather than...
a == [1,2,3]
...which I'm presuming is what you actually want.
For that result, use either
a += b
or
a.extend(b)

Categories

Resources