2d array of zeros

Python

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

for Python 3 (no more xrange), the preferred answer

zeros = [ [0] * N for _ in range(M)]

for M x N array of zeros

Solution 3 - Python

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.

Solution 4 - Python

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]]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionyakxxxView Question on Stackoverflow
Solution 1 - PythonmgilsonView Answer on Stackoverflow
Solution 2 - PythonZhe HuView Answer on Stackoverflow
Solution 3 - PythonIvan MushketykView Answer on Stackoverflow
Solution 4 - PythonCrabigator360View Answer on Stackoverflow