Python two-dimensional array – changing an element

Question:

I have this 7×7 two-dimensional array:

l=[[1, 1, 1, 1, 1, 1, 1],
  [1, 0, 2, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 1, 1, 1, 1, 1, 1]]

As you can see, l[1][2]=2. When I print it, the element is printed correctly. No problem here. But when I try to change it from “2” to “3” or any other number, the program changes all the elements on that column (in this case the 3rd column) except for the first and last ones. For example, if I type this code:

l[1][2]=5

and then print the two-dimensional array, I get this:

l=[[1, 1, 1, 1, 1, 1, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 1, 1, 1, 1, 1, 1]]

This happens with every element that I choose. Instead of changing only that element, it changes the entire column.
Does anyone know what might be the problem? Thank you!

Asked By: Joker

||

Answers:

I’m gonna take a stab at this one even though the behavior you describe (as you’ve described it) isn’t possible.

If you create a list, you need to make sure that each sublist is a different list. Consider:

a = []
b = [a, a]

Here I’ve created a list where both of the sublists are the exact same list. If I change one, it will show up in both. e.g.:

>>> a = []
>>> b = [a, a]
>>> b[0].append(1)
>>> b
[[1], [1]]

you’ll frequently see this behavior with a list initialized using the * operator:

a = [[None]*7]*7

e.g.

>>> a = [[None]*7]*7
>>> a
[[None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None]]
>>> a[0][1] = 3
>>> a
[[None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None]]

The fix is to not use the * 7 on the outer list (the inner list is OK since None is immutable):

a = [[None]*7 for _ in range(7)]

e.g.:

>>> a = [[None]*7 for _ in range(7)]
>>> a[0][1] = 3
>>> a
[[None, 3, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None]]
Answered By: mgilson

You’ve constructed your list wrong.

The middle items are all referring to the same list, so updating one causes the change to be reflected in the others

If you show the code you’re using to construct the list, I can show you how to fix it.

Alternatively

l = [sublist[:] for sublist in l]

before you begin modifying the lists will decouple all those into new lists

Answered By: John La Rooy
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.