Hi there i'm having troubles while copying arrays. I know there is really good posts about this but they dont resolve my problems.
First of all Im trying to copy nested arrays so the copy using slice do not work:
new_list = old_list[:]
This does not work when used with nested arrays, and I understand why it doesn't.
For my purposes i need to work with nested arrays so i've been using:
new_list = list(old_list)
This does copy correctly nested arrays but has a strange behavior when used inside a method. Here is an example code:
Edited Code:
def copy_and_reset(data):
import copy
events_data=list(data)
reset_to_0(data)
return events_data
def reset_to_0(the_array):
for i, e in enter code hereenumerate(the_array):
if isinstance(e, list):
reset_to_0(e)
else:
the_array[i] = 0
a=[[1,1,1,1,1],[2,2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4]]
b=copy_and_reset(a)
print a
print b
b=list(a)
a.append([22,22])
print a
print b
And here is the output:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0], [22, 22]]
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0]]
Some idea what happens there? The only way to correctly copy an array inside a method is:
new_list = copy.deepcopy(old_list)
When you are copying the list you are just creating a reference to the lists contained in A. Here is a visualaztion of whats happening:
If you want to step though and view whats happening you should check out PythonTutor
Related
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
I have trouble declaring a two-dimensional list in Python. Below are two different matrices; A and R. When changing the content of a single cell I am successful in the R-matrix, but not so much in the A-matrix, as the value-input affect the entire column and not only the single cell.
Why does this happen? I would prefer the A-style of declaring the matrix.
n=6
A = [[0]*n]*n
R=[[0,0,0,0,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0]]
R[1][1]=5
A[1][1]=5
print(R)
print(A)
The output from the two operations is:
[[0, 0, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
[[0, 5, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0], [0, 5, 0, 0, 0, 0]]
A = [[0]*n]*n creates multiple copies of the same list. This is why changing one affects every other one
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 7 years ago.
s is a list of lists of integers with all values initialized to zero. I would like to increment only the first element of the first row by one, but the following command increments the first element of every row by one. How may I achieve this?
In [6]: s = [[0]*4]*4
In [7]: s[0][0] += 1
In [8]: s
Out[8]:
[[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0]]
Okay! Thanks for the advice, the problem was in my construction of s.
If s is truly a list of lists (and not a list containing multiple references to the same list), what you did works, your issue must be elsewhere
>>> s = [[0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0]]
>>> s[0][0]
0
>>> s[0][0] = 1
>>> s
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
You made your lists "incorrectly" in the first place; each element of your list simply points to the same single list. When you update that list they all update.
Make the list of lists using code something like this instead:
s = [[0 for _ in range(5)] for _ in range(5)]
This is classical Python oversight since lists assignments are done by references not by deep copy.
For example if you constructed using this way that's where it would have gone wrong.
>>> zeros = [0,0,0,0]
>>> s = [zeros,zeros,zeros,zeros]
>>> s[0][0]+=1
>>> s
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
So while copying lists use as below
>>> s = [list(zeros), list(zeros), list(zeros), list(zeros)]
>>> s[0][0]+=1
>>> s
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
I'm trying to print a list as a table
The following code creates specified amount of rows and columns (in other words, it creates a list of a specified size).
finalgrid1 =[[0 for j in range(keyword_size)] #print rows (size of keyword)
for i in range(1 + new_grid_size)] #print column (size of ciphers)
print(finalgrid1)
The result printed is (when keyword_size = 3):
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Could someone show me how to print it in the following format.
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
I'm working on creating a Cipher encoder and decoder program as part of an assignment.
I've implemented the majority of it already - just stuck with printing it in the right format (as a table).
Btw, I am not asking you to apply any changes whatsoever, I only want to know how to print the list in the format of a table, that's all.
I appreciate your help
Try this, essentially prints each list out until there are none left to print
i = 0
while i < len(finalgrid1):
print finalgrid1[i]
i += 1
Stringify each list and join them together:
>>> grid = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>>
>>> print('\n'.join(str(x) for x in grid))
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
There is no array type in python, but to emulate it we can use lists. I want to have 2d array-like structure filled in with zeros. My question is: what is the difference, if any, in this two expressions:
zeros = [[0 for i in xrange(M)] for j in xrange(M)]
and
zeros = [[0]*M]*N
Will zeros be same? which one is better to use by means of speed and readability?
You should use numpy.zeros. If that isn't an option, you want the first version. In the second version, if you change one value, it will be changed elsewhere in the list -- e.g.:
>>> a = [[0]*10]*10
>>> a
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
>>> a[0][0] = 1
>>> a
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
This is because (as you read the expression from the inside out), you create a list of 10 zeros. You then create a list of 10 references to that initial list of 10 zeros.
Note that:
zeros = [ [0]*M for _ in range(N) ] # Use xrange if you're still stuck in the python2.x dark ages :).
will also work and it avoids the nested list comprehension. If numpy isn't on the table, this is the form I would use.
for Python 3 (no more xrange), the preferred answer
zeros = [ [0] * N for _ in range(M)]
for M x N array of zeros
In second case you create a list of references to the same list. If you have code like:
[lst] * N
where the lst is a reference to a list, you will have the following list:
[lst, lst, lst, lst, ..., lst]
But because the result list contains references to the same object, if you change a value in one row it will be changed in all other rows.
Zhe Hu's answer is the safer one and should have been the best answer. This is because if we use the accepted answer method
a = [[0] * 2] * 2
a[0][0] = 1
print(a)
will give the answer
[[1,0],[1,0]]
So even though you just want to update the first row first column value, all the values in the same column get updated. However
a = [[0] * 2 for _ in range(2)]
a[0][0] = 1
print(a)
gives the correct answer
[[1,0],[0,0]]
Initializing a matrix as so seems to link the rows so that when one row changes, they all change:
>>> grid = [[0]*5]*5
>>> grid
[[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
>>> grid[2][2] = 1
>>> grid
[[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0]]
How can I avoid this?
grid = [[0]*5 for i in range(5)]
Note: [int]*5 copies the int 5 times (but when you copy an int you just copy the value). [list]*5 copies the reference to the same list 5 times. (when you copy a list you copy the reference that points to the list in memory).