Appending to 2D lists in Python [duplicate] - python

This question already has answers here:
2D list has weird behavor when trying to modify a single value [duplicate]
(3 answers)
Closed 3 years ago.
I've encountered what I think is a strange behavior in Python, and I'd like somebody to explain it if possible.
I've created an empty 2D list
listy = [[]]*3
print listy
[[], [], []]
The following works as I'd expect:
listy[1] = [1,2] yields [[], [1,2], []]
listy[1].append(3) yields [[], [1,2,3], []]
However, when I append to one of the empty lists, python appends to ALL of the sublists, as follows:
listy[2].append(1) yields [[1], [1,2,3], [1]].
Can anyone explain to me why this behavior occurs?

You haven't created three different empty lists. You've created one empty list, and then created a new list with three references to that same empty list. To fix the problem use this code instead:
listy = [[] for i in range(3)]
Running your example code now gives the result you probably expected:
>>> listy = [[] for i in range(3)]
>>> listy[1] = [1,2]
>>> listy
[[], [1, 2], []]
>>> listy[1].append(3)
>>> listy
[[], [1, 2, 3], []]
>>> listy[2].append(1)
>>> listy
[[], [1, 2, 3], [1]]

[[]]*3 is not the same as [[], [], []].
It's as if you'd said
a = []
listy = [a, a, a]
In other words, all three list references refer to the same list instance.

Came here to see how to append an item to a 2D array, but the title of the thread is a bit misleading because it is exploring an issue with the appending.
The easiest way I found to append to a 2D list is like this:
list=[[]]
list.append((var_1,var_2))
This will result in an entry with the 2 variables var_1, var_2. Hope this helps!

Related

What's the difference between the two ways of Python to generate empty nested list and append? [duplicate]

This question already has answers here:
Changing an element in one list changes multiple lists [duplicate]
(4 answers)
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 2 years ago.
I notice this interesting thing in python:
>>> B = [[]*5 for _ in range(5)]
>>> B
[[], [], [], [], []]
>>> B[0].append(1)
>>> B
[[1], [], [], [], []]
>>>
Then I do this:
>>> B = [[]]*5
>>> B
[[], [], [], [], []]
>>> B[0].append(1)
>>> B
[[1], [1], [1], [1], [1]]
>>>
It seems B = [[]]*5 and B = [[]*5 for _ in range(5)] generate the same empty list B but why they behave different when using append? Thank you for anyone who cares to explain!
Because in second one you don't create new empty list. you just add the same list 5 time. Because of that when you select the first one and append to it t will affect on all of them. Because all are the same.
try this for sure in second one:
print(B[0] is B[1])

Wrong understanding of lists in Python? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
I am new to Python, so I apologize if this question is naive.
I consider a list elements = [3, 6, 7]. I would like to write a series of instructions which transform the list l = [[], [], []] into l = [[3], [6], [7]]. If I write the (naive) code below :
pos = 0
for i in range(3):
l[i].append(elements[i])
print(l)
then the output is not as I expected. Indeed, the list l becomes l=[[3, 6, 7], [3, 6, 7], [3, 6, 7]]. My reasoning was the following one : when i=0 only l[0] (the first element of l) should be modified. However, it is not the case. After the first run in the loop, the list l is : l = [[3], [3], [3]]. Where am I wrong ?
Of course, this could be easily solved using list comprehension:
l = [[elements[j]] for j in range(3)]
The problem is in the part of the code you haven't posted (that's why you should post complete examples when you ask questions here).
What has happened is that l contains three references to the same list. When you append an element to that list and then print l, you still see three copies of that list.
You need to create l in a way that truly makes three separate lists:
l = [ [], [], [] ] #good
l = [ [] for x in range(3) ] #good
l = [ [] ] * 3 #bad
Three copies of the same list
It appears that you've constructed your list 'l' not from three empty lists, but of three references to the same single empty list. This means that any changes done to it through l[0] are reflected also if you look at the same list through l[1].

Python: Appending an element to an element of a list of lists [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
Could somebody please explain the following behaviour?
X=2*[[]]
print X
X[0].append(1)
print X
yields
[[], []]
[[1], [1]]
I would expect the last list to be [[1], []]. Indeed, the following
X=[[],[]]
print X
X[0].append(1)
print X
yields
[[], []]
[[1], []]
Why this difference?
The multiplication syntax you used creates a shallow copy of the contents. Each list element within will be a new reference to the same list.
The second example you give actually produces a list of two different lists.
y = 2*[x]
is roughly equivalent to doing
y = [x] + [x]
The x in both places refers to the same list.
>>> y = 2*[[]]
>>> y[0].append(1)
>>> y
[[1], [1]]
>>> x = []
>>> y = [x] + [x]
>>> y
[[], []]
>>> y[0].append(1)
>>> y
[[1], [1]]
To create a list that functions as your second example, try
>>> y=[[] for n in range(2)]
>>> y[0].append(1)
>>> y
[[1], []]

Python multiply sequence trick [duplicate]

This question already has answers here:
Generating sublists using multiplication ( * ) unexpected behavior [duplicate]
(5 answers)
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
the trick is:
IPython prompt:
In [1]: A = [ [] ] * 2
In [2]: A
Out[2]: [[], []]
In [3]: A[0].append(1)
In [4]: A
Out[4]: [[1], [1]]
Obvious, it's not my expected result, what's I want is [[1], []]. So why? I found no ref in the docs about python multiply sequence.
And is there any elegant(use no any explicit loop) ways to do that?
A = [ [] ] * 2 creates a list with two references to the same list:
>>> A = [ [] ] * 2
>>> id(A[0])
24956880
>>> id(A[1])
24956880
>>> id(A[0]) == id(A[1])
True
>>>
Instead, you need to use a list comprehension:
>>> A = [[] for _ in xrange(2)]
>>> A
[[], []]
>>> A[0].append(1)
>>> A
[[1], []]
>>>
Note that, if you are on Python 3.x, you will need to replace xrange with range.
[ [] ] is an array containing (a reference to) a list. When you multiply it by 2, you get a list containing two references to the same list. Try this:
A = [[] for i in range(5)]
It will generate a new empty list for every tick of range.
There can't really be a no-loop version of this, because you really need to construct multiple lists; there can be no shortcut.

python - Add a number to an integer inside a nested list [duplicate]

This question already has answers here:
Abnormal list behaviour
(2 answers)
Closed 9 years ago.
This is MWE of what I'm trying to do:
lis = []
# Initialize empty list
for i in range(2):
lis.append([[0]]*2)
# First print
print lis
# Second print
print lis[0][1][0]
# Modify item
lis[0][1][0] += 1
# Third print
print lis
The first print returns the list as [[[0], [0]], [[0], [0]]] which is correct, I have a first list which is composed of several lists, each one also composed of several lists (I need this nested lists for what I'm doing). The second print returns the item in indexes 0 and 1 as 0 which is also correct. But the third print shows me the new list as:
[[[1], [1]], [[0], [0]]]
instead of:
[[[0], [1]], [[0], [0]]]
which is what I actually aimed at. What am I doing wrong?
That is happening because both inner lists are actually copies of same object, so modifying one will affect the other one as well.
>>> l = [[0]]*2
>>> [id(x) for x in l]
[145328716, 145328716] #same IDs
>>> l[0].append(4)
>>> l
[[0, 4], [0, 4]]
Use a list comprehension to avoid that:
>>> l = [[0] for _ in xrange(2)]
>>> [id(x) for x in l] #Different IDs
[145327372, 145327500]
>>> l[0].append(4)
>>> l
[[0, 4], [0]]

Categories

Resources