Appending in nested arrays causes all arrays to be appended [duplicate] - python

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 8 months ago.
Possible dupe: Append value to one list in dictionary appends value to all lists in dictionary
I've encountered a problem in using nested arrays, where all elements are updated, when I only want to append to a specific index.
x = [[]] * 6
x[0].append(1)
# expected: [[1], [], [], [], [], []]
# result: [[1], [1], [1], [1], [1], [1]]
What I'm guessing is that x[0] returns [], which turns the statement to [].append(1) and updates all empty lists. This is supported by the fact that non-empty sets will not be changed.
x = [[]] * 6
x[1] = [0]
x[0].append(1)
# [[1], [0], [1], [1], [1], [1]]
I currently do this workaround to assign the value:
x = [[]] * 6
y = x[0].copy()
y.append(1)
x[0] = y
I want to understand 1) why python would evaulate the x[0] bit and make [].append() apply to multiple elements in the list, if my theory is correct and 2) if there is a better way to add values in a nested list.

The statement x = [[]] * 6 creates a list with 6 references to the same list. Thus, when you append an element to any of them, the others are also updated.
When you say x[1] = [0], you've replaced x[1] entry with a new list. Thus, when updating another entry this new list will not be updated.
If you want to create a list that consists of 6 independent lists, do
[[] for _ in range(6)]

In python, list, dict, set, tuples are collection data types. It means, if you declare a variable based on collection, you have the address of the collection.
If you duplicate a collection, you have the same address for every duplication. It is the case when you do it: x = [[]] * 6
If you modify one element, it affects all of his copies.

In line x = [[]] * 6, you creating a list x with 6 reference to the same inner list []. To make it simple, x = [[]] * 6 is equivalent to:
inner_list = []
x = []
for _ in range(6):
x.append(inner_list) # here same 'inner_list' is appended 6 times
So, what you want to do here is:
x = []
for _ in range(6):
inner_list = []
x.append(inner_list) # here you are creating 6 different 'inner_list' and appending it to 'x'

Related

Unexpected results using zip to create dict from two lists [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I intend to initialize a list of list with length of n.
x = [[]] * n
However, this somehow links the lists together.
>>> x = [[]] * 3
>>> x[1].append(0)
>>> x
[[0], [0], [0]]
I expect to have something like:
[[], [0], []]
Any ideas?
The problem is that they're all the same exact list in memory. When you use the [x]*n syntax, what you get is a list of n many x objects, but they're all references to the same object. They're not distinct instances, rather, just n references to the same instance.
To make a list of 3 different lists, do this:
x = [[] for i in range(3)]
This gives you 3 separate instances of [], which is what you want
[[]]*n is similar to
l = []
x = []
for i in range(n):
x.append(l)
While [[] for i in range(3)] is similar to:
x = []
for i in range(n):
x.append([]) # appending a new list!
In [20]: x = [[]] * 4
In [21]: [id(i) for i in x]
Out[21]: [164363948, 164363948, 164363948, 164363948] # same id()'s for each list,i.e same object
In [22]: x=[[] for i in range(4)]
In [23]: [id(i) for i in x]
Out[23]: [164382060, 164364140, 164363628, 164381292] #different id(), i.e unique objects this time

Insert Tuple Into 2D Array [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I intend to initialize a list of list with length of n.
x = [[]] * n
However, this somehow links the lists together.
>>> x = [[]] * 3
>>> x[1].append(0)
>>> x
[[0], [0], [0]]
I expect to have something like:
[[], [0], []]
Any ideas?
The problem is that they're all the same exact list in memory. When you use the [x]*n syntax, what you get is a list of n many x objects, but they're all references to the same object. They're not distinct instances, rather, just n references to the same instance.
To make a list of 3 different lists, do this:
x = [[] for i in range(3)]
This gives you 3 separate instances of [], which is what you want
[[]]*n is similar to
l = []
x = []
for i in range(n):
x.append(l)
While [[] for i in range(3)] is similar to:
x = []
for i in range(n):
x.append([]) # appending a new list!
In [20]: x = [[]] * 4
In [21]: [id(i) for i in x]
Out[21]: [164363948, 164363948, 164363948, 164363948] # same id()'s for each list,i.e same object
In [22]: x=[[] for i in range(4)]
In [23]: [id(i) for i in x]
Out[23]: [164382060, 164364140, 164363628, 164381292] #different id(), i.e unique objects this time

Why does filling in one row in Python fill the entire array? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I intend to initialize a list of list with length of n.
x = [[]] * n
However, this somehow links the lists together.
>>> x = [[]] * 3
>>> x[1].append(0)
>>> x
[[0], [0], [0]]
I expect to have something like:
[[], [0], []]
Any ideas?
The problem is that they're all the same exact list in memory. When you use the [x]*n syntax, what you get is a list of n many x objects, but they're all references to the same object. They're not distinct instances, rather, just n references to the same instance.
To make a list of 3 different lists, do this:
x = [[] for i in range(3)]
This gives you 3 separate instances of [], which is what you want
[[]]*n is similar to
l = []
x = []
for i in range(n):
x.append(l)
While [[] for i in range(3)] is similar to:
x = []
for i in range(n):
x.append([]) # appending a new list!
In [20]: x = [[]] * 4
In [21]: [id(i) for i in x]
Out[21]: [164363948, 164363948, 164363948, 164363948] # same id()'s for each list,i.e same object
In [22]: x=[[] for i in range(4)]
In [23]: [id(i) for i in x]
Out[23]: [164382060, 164364140, 164363628, 164381292] #different id(), i.e unique objects this time

Creating a multidimensional list and appending element[] [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 6 years ago.
I only want to append [1] to the first list element of the main list, tree, but [1] gets appended to each list element.
tree = [[]] * 5
tree[0].append([1])
print tree
>>>[[[1], [1], [1], [1], [1]]]
What I want:
>>>[[[1]],[],[],[],[]]
The way you create the list (tree = [[]] * 5) is the problem. All the 5 lists inside the list are identical objects which you can see when using the method id():
>>> tree = [[]] * 5
>>> id(tree[0])
139859652123032
>>> id(tree[1])
139859652123032
The solution would be:
>>> tree = [[], [], [], [], []]
>>> tree[0].append([1])
>>> tree
[[[1]], [], [], [], []]
My problem was that multiplying with * creates references of the same element. I should use:
tree = [[] for i in xrange(5)]
Use a for statement to iterate and add each branch
tree = [[] for i in xrange(5)]
# xrange() and range() will have the same result, but the former is a cheaper iterator
Finally, append '[1]' to the first list
tree[0].append([1])

A sequence of empty lists of length n in Python? [duplicate]

This question already has answers here:
Python: fastest way to create a list of n lists
(5 answers)
Closed 8 years ago.
In python []*2, gives []
What is the simplest way to get [[],[]] instead?
You probably want:
[[] for _ in range(n)]
Unlike [[]] * n, this will give you unique inner lists (appending to one doesn't append to them all). e.g.:
>>> x = [[] for _ in range(n)]
>>> x[0].append(1)
>>> x
[[1], [], []]
compared to:
>>> x = [[]] * 3
>>> x[0].append(1)
>>> x
[[1], [1], [1]]
Note that this latter idiom ([[]] * n) is a very common mistake that crops up around here in different contexts pretty frequently.
Use comprehension:
[[] for _ in range(2)]
That's because (e.g.) [1]*3 gives [1,1,1], i.e., a sequence containing the contents of the list.
Hence you want to duplicate the value []:
a = [[]]*2
giving
[[], []]
Because of the way the * operator works, this gives copies of the same list. Hence, if you try to modify either of those inner empty lists, it effects both of them. (Since they're empty, just about the only thing you can do is append to them; i.e., a[0].append(1) gives [[1],[1]].) This is possibly, but unlikely, what you want.

Categories