Why can't I assign to 3d lists properly? [duplicate] - python

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
Let's say that I make a 3D list
list = [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
and I run
list[0][0][0] = 1 #set the first element of the first list of the first list to 1
print(list)
I'd expect to get
[[[1, 0], [0, 0]], [[0, 0], [0, 0]]]
but instead, I get
[[[1, 0], [1, 0]], [[1, 0], [1, 0]]]
Can someone figure out how to make it assign a variable to ONLY ONE element of a 3D list, instead of every first element? Thanks!
If it matters, I'm using Python 3.7 32-bit.

I have reproduced your results by making an assumption about how you actually defined your list. I assume that you defined some variable such as ab below and used that to create your list. However, the new list is still a bunch of references to your ab variable, so changing one actually changes ab which will affect your whole list.
ab = [0,0]
mylist = [[ab,ab],[ab,ab]]
mylist[0][0][0] = 1
print(mylist," ",ab)
OUTPUT
[[[1, 0], [1, 0]], [[1, 0], [1, 0]]] [1, 0]
To resolve this, simple initialize your lists with 0 instead of some variable:
mylist = [[[0,0],[0,0]],[[0,0],[0,0]]]
or
mylist = [[[0 for _ in range(2)] for _ in range(2)] for _ in range(2)]

Related

Could not get the nested array initialization work? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 2 years ago.
i am puzzled by this behavior
r,c = (5,2)
slist = [[0]*c]*r
print(slist)
for i in range(r):
slist[i][0] = i
print(slist)
Output is
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
[[4, 0], [4, 0], [4, 0], [4, 0], [4, 0]]
When you do [[0] * c] * r, you create a list where every element is a reference to the same list. So, when you change one, they all change. Use a list comprehension with a range instead to create unique lists:
slist = [[0] * c for _ in range(r)]
See here for more info.

Update value in Multidimensional list in Python [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
I have an list like the following
line_37_data = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
When I print line_37_data[0][0] , the value 0 is printed.
When I update the list as line_37_data[0][0] = 5, the list gets modified like below
[[5, 0, 0], [5, 0, 0], [5, 0, 0]]
How can I can update the value in the list based on the index ?
Note :- I don't use NumPy. This is pure plain Python without any libraries. I am using 2.7 and not Python 3
If you pass in the same list as each element of your outer list, manipulating it will show in each place it appears. If you're just looking to fill a 2d list with zeros, list comprehension would be easy:
def generate_2d(h, w):
return [[0 for x in range(w)] for y in range(h)]
array = generate_2d(3, 3)
# Format is array[y][x] based on names in function
array[0][0] = 5
array[1][2] = 7
assert array == [
[5, 0, 0],
[0, 0, 7],
[0, 0, 0]]

change list elements [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python List Index
result=[range(3)]*2
for i in range(len(result)):
result[i][2]=4*i
print result
I would expected [[0, 1, 0], [0, 1, 4]]
Why do I get [[0, 1, 4], [0, 1, 4]]
Thank you!
When you do [range(3)] * 2, it makes a list with two references to the same list inside, so modifying result[0] and result[1] each modify both.
Use [range(3) for i in range(2)] to make a list with two different results of range(3) in it.
List "result" is: [[0, 1, 2], [0, 1, 2]]
Your iteration is: "for i in range(len(result))"
len(result) is: 2
range(2) is: [0,1]
meaning:
first time:
result[0][2]=4*0
second time:
result[1][2]=4*1
which gives you the result [[0, 1, 4], [0, 1, 4]]
This is what is doing step by step.
If you add a "break" to the iteration you see the result is [[0, 1, 0], [0, 1, 0]]
The "result" list works by reference. When it is called, it is pointing to the same object.

Python list bug or am I wrong?

I have constructed a 3 level nested list
#run on Python 3.2.3 32 bit on Win 7
L2=list(0 for i in range(2))
L3=list(L2 for i in range(3))
L4=list(L3 for i in range(4))
#give a new value to the very first number in list:
L4[0][0][0]=5
print("L4:")
print(L4)
#outputs erronously:
#[[[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]]]
The same list given explicitly
#the same L4 given explicitly:
anotherL4=[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
print("anotherL4:")
#give a new value to the very first number:
anotherL4[0][0][0]=5
print(anotherL4)
#outputs correctly:
#[[[5, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
You're wrong. You've copied the reference multiple times, which means they're actually all the same list.
When you write list(L3 for i in range(4)), you are telling it to yield the same list L3 on each iteration of the generator comprehension. When you subsequently modify that list, the modifications show up everywhere, because all of them are references to the same list.
You could get the effect you seem to want by doing
list(list(L3) for i in range(4))
since using list(L3) makes a new list.
Just to elaborate,
a = 1
b = 2
c = [a,b]
a += 1
print c
Your problem is that you built a list of list references rather than a list of lists. Since the references all pointed back to a single list, when you mutate that single list, all the references show the change.
L0 = range(3)
L1 = range(3)
print(id(L0)) # prints a number
print(id(L1)) # prints a different number
print(id(L0) == id(L1)) # prints False
print(L0 is L1) # prints False; not same objects
print(L0 == L1) # prints True; values match
# your original code:
L2=list(0 for i in range(2))
L3=list(L2 for i in range(3))
L4=list(L3 for i in range(4))
print(L3[0] is L2) # prints True; L3[0] is a reference to L2
We can fix it and explicitly show what we are doing by using copy.deepcopy():
import copy
L2 = [0 for i in range(2)]
L3 = [copy.deepcopy(L2) for i in range(3)]
L4 = [copy.deepcopy(L3) for i in range(4)]
#give a new value to the very first number in list:
L4[0][0][0]=5
print("L4:")
print(L4)
Note that instead of making a generator expression and passing it to list() to force it to be expanded out to a list, I just used list comprehensions in the above code to directly make lists.
More usually if you want to do this crazy thing, you should maybe just nest some list comprehensions:
L4 = [[[0 for _ in range(2)] for _ in range(3)] for _ in range(4)]
This makes it pretty clear that we are building a new list of lists of lists. And if you use copy.deepcopy() you are basically just copying a bunch of zeroes, so you might as well just build new lists using zeroes.

Populate a 5 * 5 list with python

I have a list[5][5] to populate... it looks like a table with 5 columns and 5 rows.
Each cell can be either one or zero.
I want to find different 2^25 possibility that can exist. Each possiblity is a combination of either 0 or 1 in a 5*5 table/list
How can I do that? With nested loop or something?
I suggest you start small... with a 1x1 list first and check that you can display both of the available combinations:
[[0]]
[[1]]
Next up, try a 2x2 list. There are 16 different lists to display:
[[0, 0], [0, 0]]
[[0, 0], [0, 1]]
[[0, 0], [1, 0]]
[[0, 0], [1, 1]]
[[0, 1], [0, 0]]
[[0, 1], [0, 1]]
[[0, 1], [1, 0]]
[[0, 1], [1, 1]]
[[1, 0], [0, 0]]
[[1, 0], [0, 1]]
[[1, 0], [1, 0]]
[[1, 0], [1, 1]]
[[1, 1], [0, 0]]
[[1, 1], [0, 1]]
[[1, 1], [1, 0]]
[[1, 1], [1, 1]]
If you've got the algorithm right for 1x1 and 2x2, then you should be able to generalise it to print your 5x5.
Good luck!
Update
Since you appear to be still struggling, here's a little extra help.
Break this problem into smaller problems. I'd start with generating the values. If you ignore the list notation in my examples above, you'll see that the sequence of values is one that is recognisable to every computer scientist on the planet. It's also pretty easy to generate in Python using bin() and str.zfill().
The second problem is putting them into lists. This isn't too hard either. Supposing the first value in your sequence is '0000'. You know that your lists are two rows by two columns. You can put the first two characters into a list and put that list into a list. Then put the next two characters into a list and append that list to the previous one. Done. Repeat for each value in the sequence.
Hope this helps.
You could try:
import itertools
gen = itertools.product((0,1),repeat=25)
To create a generator to get all of the combinations in 1d and then reshape the data as needed.

Categories