2

Please see the code below, why by doing

array[0][0] = 'Tadaaaa'

changed 5 elements instead of one?

First, create an empty array:

x, y = 5, 3

# when you multiply it's copying, so the ids of each item is the same
array = [[set()] * y] * x
array

I will get:

[[set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()],
 [set(), set(), set()]]

Then assign a value to elements:

array[3][2].add('BBC')
array

I will get:

[[{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}]]

But when I do:

array[0][0] = 'Tadaaaa'
array

I get:

[['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}],
 ['Tadaaaa', {'BBC'}, {'BBC'}]]

What's going on here?

I thought I would get something like this:

[['Tadaaaa', {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}],
 [{'BBC'}, {'BBC'}, {'BBC'}]]
DanZimmerman
  • 1,626
  • 6
  • 23
  • 45

2 Answers2

5

First, these are not arrays; they are lists.

Second, using * creates a list of references to the same set object, not a list of references to distinct set objects.

>>> x = [set()]*3
>>> id(x[0]), id(x[1]), id(x[2])
(4297985280, 4297985280, 4297985280)

Instead, use a list comprehension to ensure that set() is called once per element.

>>> x = [set() for _ in range(3)]
>>> id(x[0]), id(x[1]), id(x[2])
(4298169136, 4298363424, 4298363656)

You can use nested list comprehensions to get the nested list you want:

>>> x, y = 5, 3
>>> array = [[set() for _ in range(y)] for _ in range(x)]
>>> for x in array:
...   map(id, x)
...
[4298169136, 4298363424, 4298363656]
[4297985280, 4298363888, 4298364120]
[4298364352, 4298364584, 4298364816]
[4298365048, 4298365280, 4298365512]
[4298365744, 4298365976, 4298366208]

As you can see, each element in the array is a distinct set object.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Why does `array[3][2].add('BBC')` change all elements while `array[0][0] = 'Tadaaaa'` only changes one column? – Bob Baxley May 20 '17 at 13:00
  • 2
    Because the first one invokes a method on the mutable object referenced by `array[3][2]` (which is the same object referenced by *every* element of the list). The second one changes the reference stored in `array[0][0]`, overwriting the previous reference with a reference to a `str` object. You should read https://nedbatchelder.com/text/names.html. – chepner May 20 '17 at 13:04
  • This is a very good article to get better understanding of value assignment. Thanks for sharing chepner! – DanZimmerman May 20 '17 at 13:35
0

this is duplicate question , you are repeating the same element (empty set) by putting:

array = [[set()] * y] * x

You need to use for loop for initializing the array as one solution That's all

Community
  • 1
  • 1
Yasin Yousif
  • 969
  • 7
  • 23