Copying nested lists in Python
Question:
I want to copy a 2D list, so that if I modify one list, the other is not modified.
For a one-dimensional list, I just do this:
a = [1, 2]
b = a[:]
And now if I modify b
, a
is not modified.
But this doesn’t work for a two-dimensional list:
a = [[1, 2],[3, 4]]
b = a[:]
If I modify b
, a
gets modified as well.
How do I fix this?
Answers:
b = [x[:] for x in a]
For a more general solution that works regardless of the number of dimensions, use copy.deepcopy()
:
import copy
b = copy.deepcopy(a)
Whis b = a[:]
doesn’t work for nested list(or say muti-dimension list)?
a = [[1, 2],[3, 4]]
b = a[:]
Answer: Though when we are copying the list a
using slicing[:]
operation but the inner sub-list still refers to the inner-sub list of list b
Note: We can check the reference using id()
in python.
Let’s understand using an example.
>>> a = [[1,2],[3,4]]
>>> id(a)
140191407209856 # unique id of a
>>> b=a
>>> id(b)
140191407209856
>>> b=a[:] # Copying list a to b with slicing
>>> id(b)
140191407209920 # id of list b changed & is not same as id of list a
>>> id(a[0])
140191407188544
>>> id(b[0])
140191407188544
>>> id(a[0])==id(b[0]) # id of both a[0] & b[1] is same.
True
So, slicing won’t change the reference for objects inside the list.
You can notice from above that reference of a[0]
is the same as b[0]
.
When you copy a 2D list to another, it adds a reference to it not the actual list.
Instead you can use:
- b =
copy.deepcopy(a)
- b =
[item[:] for item in a]
- b =
[item.copy() for item in a]
- b =
[list(item) for item in a]
- b =
[copy.copy(item) for item in a]
- b =
[]; b.extens[a]
Below is the comparison of the time complexity of all available copy methods (source)
-
10.59 sec (105.9us/itn) – copy.deepcopy(old_list)
-
10.16 sec (101.6us/itn) – pure python Copy()
method copying classes with deepcopy
-
1.488 sec (14.88us/itn) – pure python Copy()
method not copying classes (only dicts/lists/tuples)
-
0.325 sec (3.25us/itn) – for item in old_list: new_list.append(item)
-
0.217 sec (2.17us/itn) – [i for i in old_list]
(a list comprehension)
-
0.186 sec (1.86us/itn) – copy.copy(old_list)
-
0.075 sec (0.75us/itn) – list(old_list)
-
0.053 sec (0.53us/itn) – new_list = []; new_list.extend(old_list)
-
0.039 sec (0.39us/itn) – old_list[:]
(list slicing)
You can use the following for two-dimensional nested arrays:
b = [[y for y in x] for x in a]
I want to copy a 2D list, so that if I modify one list, the other is not modified.
For a one-dimensional list, I just do this:
a = [1, 2]
b = a[:]
And now if I modify b
, a
is not modified.
But this doesn’t work for a two-dimensional list:
a = [[1, 2],[3, 4]]
b = a[:]
If I modify b
, a
gets modified as well.
How do I fix this?
b = [x[:] for x in a]
For a more general solution that works regardless of the number of dimensions, use copy.deepcopy()
:
import copy
b = copy.deepcopy(a)
Whis b = a[:]
doesn’t work for nested list(or say muti-dimension list)?
a = [[1, 2],[3, 4]]
b = a[:]
Answer: Though when we are copying the list a
using slicing[:]
operation but the inner sub-list still refers to the inner-sub list of list b
Note: We can check the reference using id()
in python.
Let’s understand using an example.
>>> a = [[1,2],[3,4]]
>>> id(a)
140191407209856 # unique id of a
>>> b=a
>>> id(b)
140191407209856
>>> b=a[:] # Copying list a to b with slicing
>>> id(b)
140191407209920 # id of list b changed & is not same as id of list a
>>> id(a[0])
140191407188544
>>> id(b[0])
140191407188544
>>> id(a[0])==id(b[0]) # id of both a[0] & b[1] is same.
True
So, slicing won’t change the reference for objects inside the list.
You can notice from above that reference of a[0]
is the same as b[0]
.
When you copy a 2D list to another, it adds a reference to it not the actual list.
Instead you can use:
- b =
copy.deepcopy(a)
- b =
[item[:] for item in a]
- b =
[item.copy() for item in a]
- b =
[list(item) for item in a]
- b =
[copy.copy(item) for item in a]
- b =
[]; b.extens[a]
Below is the comparison of the time complexity of all available copy methods (source)
-
10.59 sec (105.9us/itn) –
copy.deepcopy(old_list)
-
10.16 sec (101.6us/itn) – pure python
Copy()
method copying classes with deepcopy -
1.488 sec (14.88us/itn) – pure python
Copy()
method not copying classes (only dicts/lists/tuples) -
0.325 sec (3.25us/itn) –
for item in old_list: new_list.append(item)
-
0.217 sec (2.17us/itn) –
[i for i in old_list]
(a list comprehension) -
0.186 sec (1.86us/itn) –
copy.copy(old_list)
-
0.075 sec (0.75us/itn) –
list(old_list)
-
0.053 sec (0.53us/itn) –
new_list = []; new_list.extend(old_list)
-
0.039 sec (0.39us/itn) –
old_list[:]
(list slicing)
You can use the following for two-dimensional nested arrays:
b = [[y for y in x] for x in a]