Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python : how to append new elements in a list of list?

Tags:

python

list

Here is a very simple program:

 a = [[]]*3

 print str(a)

 a[0].append(1)
 a[1].append(2)
 a[2].append(3)

 print str(a[0])
 print str(a[1])
 print str(a[2])

Here is the output I was expecting:

 [[], [], []]
 [1]
 [2]
 [3]

But instead I get this :

 [[], [], []]
 [1, 2, 3]
 [1, 2, 3]
 [1, 2, 3]

There is really something I do not get here !

like image 461
Vince Avatar asked Jun 27 '12 05:06

Vince


4 Answers

You must do

a = [[] for i in xrange(3)]

not

a = [[]]*3

Now it works:

$ cat /tmp/3.py
a = [[] for i in xrange(3)]

print str(a)

a[0].append(1)
a[1].append(2)
a[2].append(3)

print str(a[0])
print str(a[1])
print str(a[2])

$ python /tmp/3.py
[[], [], []]
[1]
[2]
[3]

When you do something like a = [[]]*3 you get the same list [] three times in a list. The same means that when you change one of them you change all of them (because there is only one list that is referenced three times).

You need to create three independent lists to circumvent this problem. And you do that with a list comprehension. You construct here a list that consists of independent empty lists []. New empty list will be created for each iteration over xrange(3) (the difference between range and xrange is not so important in this case; but xrange is a little bit better because it does not produce the full list of numbers and just returns an iterator object instead).

like image 159
Igor Chubin Avatar answered Sep 28 '22 21:09

Igor Chubin


The fundamental problem with your approach is that when you multiply the list by three, the resultant list contains three of the same list. So a[0], a[1], and a[2] all reference the same thing. When you append to any of these, you append to the same list. This is why the effect of your append() calls seem to be triplicated.

Instead, generate your list-of-lists without referencing the same list. As an example, you can use list comprehension, like so.

[[] for i in range(3)]
like image 25
cheeken Avatar answered Sep 28 '22 21:09

cheeken


When you write:

a = [[]]*3

You won't make 3 copies of the inner empty list, but instead you make 3 references to the same object.

The same way, if you do:

b = [1,2,3]
c = b
c.append(4)
print b

You get as the output:

[1, 2, 3, 4]

That is because b and c are two different references (you may say two different names) to the same list. You may change the object from any reference, but you will see the results from all of them, since they point to the same thing.

like image 30
lvella Avatar answered Sep 28 '22 22:09

lvella


this will give you a clear idea, in l all object have the same id() and all are mutable so editing any one of them will automatically edit other too, as they all are just refernces to a same object with id=18671936 and in m all have different id(), so all of them are different objects.

>>> l = [[]]*4
>>> for x in l:
        print(id(x))

18671936 
18671936
18671936
18671936

>>> m=[[],[],[],[]]
>>> for x in m:
        print(id(x))

10022256
18671256
18672496
18631696

So,you should create your list like this:

>>> a=[[] for _ in range(4)]
>>> a[0].append(1)
>>> a[2].append(5)
>>> a
[[1], [], [5], []]
like image 35
Ashwini Chaudhary Avatar answered Sep 28 '22 22:09

Ashwini Chaudhary