Python | Using 2D Arrays / Lists the Right Way



Method 1a

# First way to create 1 D array

N = 5

arr = [ 0 ] * N

print (arr)

Output:

 [0, 0, 0, 0, 0] 

Method 1b

# Second way to create array 1 D

N = 5

 arr = [ 0 for i in range (N)]

print (arr)

Exit:

 [0, 0, 0, 0, 0 ] 

Extending the above, we can define 2-dimensional arrays in the following ways. 
Method 2a

# Using the above first method to create
# 2D array

rows, cols = ( 5 , 5 )

arr = [[ 0 ] * cols] * rows

print (arr)

Exit:

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

Method 2b

# Using the above second method to create
# 2D array

rows, cols = ( 5 , 5 )

arr = [[ 0 for i in range (cols)] for j in range (rows)]

print   (arr)

Output:

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

Both methods seem to give the same result as now. Let`s replace one of the elements in the array of method 2a and method 2b.

# Python 3 program to demonstrate how it works
# method 1 and method 2.

  

rows , cols = ( 5 , 5 )

  
# method 2a

arr = [[ 0 ] * cols] * rows

 
# change the first element
# first line to 1 and print the array

arr [ 0 ] [ 0 ] = 1

  

for row in arr:

print (row)

# outputs the following
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]

 
# method 2b

arr = [[ 0 for i in range (cols)] for j in range (rows)]

 
# back to this new array lets you change
# first element of the first row
# to 1 and print the array

arr [ 0 ] [ 0 ] = 1

for row in arr:

print (row)

 
# outputs the following as expected
# [1, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]

Exit:

 [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0 , 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [0, 0, 0, 0, 0] [ 0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] 

We expect only the first element of the first line to change to 1, but the first element of each line will change to 1 in method 2a. This kind of functioning is due to the fact that Python uses shallow lists, which we will try to understand.

In method 1a, Python does not create 5 integer objects, but only creates one integer object, and all indexes of the arr array point to the same an int object as shown.

If we assign 0th index to another integer, say 1, then a new integer object is created with the value 1, and then 0th index now points to this new int object as shown below

Likewise, when we create a two-dimensional array like" arr = [[0] * cols] * row ", we are in fact, we are expanding the above analogy. 
1. Only one integer object is created. 
2. One list 1d is created, and all of its indices point to the same int object at point 1.
3. Now arr [0], arr [1], arr [2]…. arr [n-1] all point to the same list object above in step 2.

The above setting can be visualized in the image below.

Now let`s change the first element in the first line" arr "as
arr [0] [0] = 1

= & gt; arr [0] points to the same list object we created above (remember that arr [1], arr [2]… arr [n-1] also point to the same list object)
= & gt ; Assigning arr [0] [0] will create a new int object with a value of 1, and arr [0] [0] will now point to this new int object. (And so it will be arr [1] [0], arr [2] [0]… arr [n-1] [0])

This can be clearly seen in the image below.

So when 2d arrays are created in this way, changing the values ​​in a certain line will affect all strings, since there is essentially only one integer object and only one list object referenced by all the rows in the array.

As you would expect, track down errors caused by this use of shallow lists. complicated. Hence the best way to declare a 2d array is

rows, cols = ( 5 , 5 )

arr = [[ 0 for i in range (cols)] for j in range (rows )]

Exit:

  

This method creates 5 separate list objects as opposed to method 2a. One way to check this — use the "is" operator, which checks if two operands refer to the same object.

rows, cols = ( 5 , 5 )

# method 2b

arr = [[ 0 for i in range (cols)] for j in range (rows)]

 
# check if arr [0] and arr [1] refer to
# same object

print (arr [ 0 ] is arr [ 1 ] ) # prints False

 
# method 2a

arr = [[ 0 ] * cols] * rows

  
# check if arr [0] and arr [1] refer to
# that same object
# prints True because there is only one
# list of the object to create.

print (arr [ 0 ] is arr [ 1 ])

Exit:

 False True