Cupitor Cupitor - 4 months ago 22
Python Question

Filling in a completely empty list of lists in an arbitrary order

I am trying to fill an

NxN
list of lists in python. In a way that if seen as a 2D array, first the main diagonal is filled and then other operations are done with other elements (not relevant here). So for example if we have
dyn_arr=[[[], [], []], [[], [], []], [[], [], []]]
in the beginning, it should first turn into:
[[[1], [], []], [[], [1], []], [[], [], [1]]]
. I assumed this code might do it:

dyn_arr = [[[]]* N] * N
idx_set = []
for pointer in range(N):
pointer_pair = [0, pointer]
while pointer_pair[0] < N and pointer_pair[1] < N:
if pointer_pair[0] == pointer_pair[1]:
dyn_arr[pointer_pair[0]][pointer_pair[1]]=[1]
pointer_pair[0] += 1
pointer_pair[1] += 1


But it outputs
[[[1], [1], [1]], [[1], [1], [1]], [[1], [1], [1]]]
. Can somebody please explain me what is going on and how I should correct it?

Answer

Be careful when creating lists using the multiplication operator. This way will multiply the references to the objects in the list; it will not create copies! So, if you create a list of lists using a = [[]] * 3, this will create a list of three elements which are all the same empty array. Changing it (using .append()) will change this one same list which is referenced in all three elements of the outer list:

a = [[]] * 3
print a  # prints "[[], [], []]"
a[0].append(4)
print a  # prints "[[4], [4], [4]]"
print a[0] is a[1]  # prints "True"

You should always create lists of lists using a list comprehension:

# instead of dyn_arr = [[[]]* N] * N use:
dyn_arr = [ [ [] for _i in range(N) ] for _j in range(N) ]

The result will look the same right after creation, but this version creates new arrays for each entry instead of additional references.

This should solve your issues resulting from the original error.