Inserting a value to a sublist in a list. PYTHON - python

This piece of code is from a tic tac toe game I am making. I have to insert a value into a sublist in a list. This is my attempt at doing just that, but it does not work (Python 3.5.1). Is it possible to use insert() to insert a value into a sublist, if so, how do you do it?
game_board_lst = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
play1_row = int(input("Player 1: What row? "))
play1_col = int(input("Player 1: What column? "))
game_board_lst.insert((play1_row - 1)(play1_col - 1), 1)

Use the subscript operator lst[index].
Since you have a list of lists, you would use lst[row][col]:
>>> game_board_lst = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> game_board_lst[1][1]=3
>>> game_board_lst
[[0, 0, 0], [0, 3, 0], [0, 0, 0]]

Based on your example, I think you would want to modify an existing value, such as:
game_board_lst[play1_row-1][play1_col-1] = 1

Related

Apending a list in a list multiple times retaining the ability to change a specific element in python

I want to create a grid with a variable number of rows and columns. What I have done to achieve this is this
BaseRow = []
for j in range (0, columns):
BaseRow.append(0)
Grid = []
for j in range (0, rows):
Grid.append(BaseRow)
So all seems fine until now, I print the rows in order with this piece of code
for i in range (1, rows+1):
print Grid[rows-i]
and a grid that looks something like this
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
is printed. Thing is, afterwards, I want to change a specific element. But when I do,
Grid[0][0] = 1
and print again, instead of just changing the rightmost down most 0 to a 1, the whole column changes, so it becomes
[1, 0, 0]
[1, 0, 0]
[1, 0, 0]
I suspect it sees that Grid is taking from BaseRow, so it changes BaseRow, and then the Grid takes the rows from BaseRow and just puts that value everywhere. I suspect .append might not be what I am looking for, but for all the research I have done I have not managed to find something else to use. If I understand correctly, .extend will not add it as a list but as individual numbers. What should I change, or how should I structure this?
Please excuse my limited knowledge, I just started programming in python half a week ago. Thanks for your help!
BaseRow = []
for j in range (0, columns):
BaseRow.append(0)
Grid = []
for j in range (0, rows):
Grid.append(BaseRow)
When you do this, the same instance of BaseRow is appended to Grid multiple times. So, if you change even row in Grid, the effect will be on all rows, as it is basically the same instance of list in all rows.
If you want a copy of BaseRow to be appended to Grid, use the below code:
for j in range(0, rows):
Grid.append(BaseRow[:])
You could also use list comprehension:
Grid = [[0 for j in range(0, columns)] for i in range(0, rows)]
Output for Columns = 3 and rows = 4:
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
Output after setting Grid[0][0] = 1:
[[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
If you ask me, I would any day use List comprehension because it's so clean and easy:
columns, rows = 3, 3
lst = [[0 for j in range(columns)] for i in range(rows)] # List of List with 3 Columns and 3 Rows
lst[0][0] = 1 # modifying a member
print (lst) # Print the result
# Result: [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
I personally prefer list comprehension but your code needs just little changes and it will serve you well. You append list and to that list you append elements:
matrix = []
for i in range(3):
matrix.append([])
for j in range(4):
matrix[-1].append(0)
print(matrix)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
matrix[0][0] = 1
print(matrix)
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

update all items in a list using function in python

Could you please tell what i'm doing wrong and how to fix it.
Thanks
I have a function.
def out(some_list):
test_list = [1,2,3,4]
result = []
for i in some_list:
if i == 1:
test_list = [0,0,0,0]
else:
test_list = test_list
result.append(test_list)
return result
if we print it out it will return:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
I need to return
[[0, 0, 0, 0], [1,2,3,4], [1,2,3,4], [1,2,3,4]]
This is because the list you are passing in this function has 1 as the value of the first element. For example:
out([1,2,3,4]) # ==> [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Going through your code step by step:
test_list = [1,2,3,4]
result = []
for i in some_list: # The value of each element in some_list
if i == 1: # If the value is "1" set test_list: [0,0,0,0]
test_list = [0,0,0,0]
else:
test_list = test_list # Otherwise set test_list to itself (doing nothing)
result.append(test_list)
for i in some_list:
The for loop value of i is the value of the element you are on in some_list, it is not the index or position of the element we are on in the list (as it appears this question intends)
if i == 1:
test_list = [0,0,0,0]
If the value is 1, then test_list will be set to [0,0,0,0]. Once this is hit only the value [0,0,0,0] will be appended to result. So if the first element is 1 then you will only see the value [0,0,0,0] in the result, otherwise you will see [1,2,3,4] until the loop hits where the value in the list some_list is 1.
Here are some examples:
out([0,1,2,3]) # [[1, 2, 3, 4], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
out([1,2,3,4]) # [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
out([2,2,5,1]) # [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [0, 0, 0, 0]]
Hopefully this makes it more clear why you are getting that result.
Edit
In terms of your updated question whats happening here is that when you call .append(fig) is simply a copy of the reference to the fig in memory. Basically whenever it changes all the copies that you appended will change as well. There are two ways you can handle this, first would be have the variable fig be defined in the scope of your loop, this way it's a new and different variable on each loop:
for i in test_list:
fig = [2, 1] # <== In the scope of the loop, so each fig is it's on variable
...
The second way is you could append fig[:], which means it will copy the array fig as a new array and pass that in for append:
for i in test_list:
if i == '0':
fig[0] = off
fig[1] = off
elif i == '1':
fig[0] = off
fig[1] = on
new_list.append(fig[:]) # <== Copy the array fig and append that value
It is because you set test_list = [0,0,0,0]
so even in test_list = test_list it is keeping the result from setting it to [0,0,0,0]
try using
def out(some_list):
test_list = [1,2,3,4]
result = []
for i in some_list:
if i == 1:
result.append([0,0,0,0])
else:
result.append(test_list)
return result

Generating nested lists from a list [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have the following list:
data = [0, 1, 0, 1, 0, 1]
I would like to write a loop that will give me the following lists:
[0]
[0, 1]
[0, 1, 0]
[0, 1, 0, 1]
[0, 1, 0, 1, 0]
That is, I want a total of five lists (one less than the length of the original list). However, I need the code to be flexible enough that no matter how long the list is, it outputs the first element, then the first two elements, and so on, as individual lists, until it reaches the length of the original list minus one.
How can I write code to do this? Is there anything more elegant than the obvious for loop?
You can use a list comprehension. Simple and easy.
In [652]: [list_[:i] for i in range(1, len(list_))]
Out[652]: [[0], [0, 1], [0, 1, 0], [0, 1, 0, 1], [0, 1, 0, 1, 0]]
This is the slick equivalent of a for loop doing the same thing:
In [654]: output = []
...: for i in range(1, len(list_)):
...: output.append(list_[:i])
...: print(output)
...:
[[0], [0, 1], [0, 1, 0], [0, 1, 0, 1], [0, 1, 0, 1, 0]]
Just a silly alternative for fun...
>>> list(itertools.accumulate([x] for x in data))[:-1]
[[0], [0, 1], [0, 1, 0], [0, 1, 0, 1], [0, 1, 0, 1, 0]]
Here's one way to do it:
my_list = [0, 1, 0, 1, 0, 1]
def one_by_one(l):
previous = []
total = len(l) - 1
for i, element in enumerate(l):
if i != total:
previous.append(element)
print previous
one_by_one(my_list)
Here I create a function, one_by_one , which iterates over the list it takes as its parameter. During iteration, it appends each list value to an empty list and prints what it has so far - only if the element is not the final one. The output is just what you wanted:
[0]
[0, 1]
[0, 1, 0]
[0, 1, 0, 1]
[0, 1, 0, 1, 0]
[0, 1, 0, 1, 0, 1]
This function just prints the output. If you would like to keep these lists for later use, then that would take a slightly different approach. Hope this helps!
for i,x in enumerate(list):
print (list[:i])

Nested List Indices [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
I have experienced some problem by using a nested list in Python in the code shown bleow.
Basically, I have a 2D list contains all 0 values, I want to update the list value in a loop.
However, Python does not produce the result I want. Is there something that I misunderstand about range() and Python list indices?
some_list = 4 * [(4 * [0])]
for i in range(3):
for j in range(3):
some_list[i+1][j+1] = 1
for i in range(4):
print(some_list[i])
The results I expected are:
[0, 0, 0, 0]
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]
But the actual results from Python are:
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]
What's going on here?
The problem is caused by the fact that python chooses to pass lists around by reference.
Normally variables are passed "by value", so they operate independently:
>>> a = 1
>>> b = a
>>> a = 2
>>> print b
1
But since lists might get pretty large, rather than shifting the whole list around memory, Python chooses to just use a reference ('pointer' in C terms). If you assign one to another variable, you assign just the reference to it. This means that you can have two variables pointing to the same list in memory:
>>> a = [1]
>>> b = a
>>> a[0] = 2
>>> print b
[2]
So, in your first line of code you have 4 * [0]. Now [0] is a pointer to the value 0 in memory, and when you multiply it, you get four pointers to the same place in memory. BUT when you change one of the values then Python knows that the pointer needs to change to point to the new value:
>>> a = 4 * [0]
>>> a
[0, 0, 0, 0]
>>> [id(v) for v in a]
[33302480, 33302480, 33302480, 33302480]
>>> a[0] = 1
>>> a
[1, 0, 0, 0]
The problem comes when you multiply this list - you get four copies of the list pointer. Now when you change one of the values in one list, all four change together:
>>> a[0][0] = 1
>>> a
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
The solution is to avoid the second multiplication. A loop does the job:
>>> some_list = [(4 * [0]) for _ in range(4)]
Actually all the objects in your list are same, so changing one changes others too:
In [151]: some_list = 4 * [(4 * [0])]
In [152]: [id(x) for x in some_list]
Out[152]: [148641452, 148641452, 148641452, 148641452]
In [160]: some_list[0][1]=5 #you think you changed the list at index 0 here
In [161]: some_list
Out[161]: [[0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0]] #but all lists are changed
Create your list this way:
In [156]: some_list=[[0]*4 for _ in range(4)]
In [157]: some_list
Out[157]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
In [158]: [id(x) for x in some_list]
Out[158]: [148255436, 148695180, 148258380, 148255852]
In [163]: some_list[0][1]=5
In [164]: some_list
Out[164]: [[0, 5, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] #works fine in this case

Initialise matrix in python [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Python list problem
I try to initialise a matrix in python.
First I did this:
>>> M=[[0]*4]*4
But here is my probleme, every line is changing when I change the first one:
>>> M
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> M[1][1]=1
>>> M
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]
So I did it this way:
>>> M= [ [ 0 for i in range(4) ] for j in range(4) ]
And ut works fine:
>>> M
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> M[1][1]=1
>>> M
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
My question is:
What these two expressions really mean ? ans why the first one is behaving this way ?
Thanks in advance for you help.
When you multiply those lists, Python is copying them by reference rather than creating entirely new objects.
A simple example might help, showing what happens with copy by reference:
>>> pie = ['apple', 'cherry', 'pecan']
>>> pie_copy = pie
>>> pie_copy[0] = 'banana'
>>> pie
['banana', 'cherry', 'pecan']
>>> pie is pie_copy
True
>>> new_pie = ['banana', 'cherry', 'pecan']
>>> pie is new_pie
False
In the same way that pie_copy and pie point to the same list, when building lists by multiplying, all the copies point to the same list.
In your second snippet using range() and list comprehensions, you aren't taking a single list and copying it several times; each iteration in the comprehension is creating a new list, so you don't suffer from the same copy by reference problem.
Because here M=[[0]*4]*4
You create a links on objects.
It's the similar as
>>> a = [0, 0, 0]
>>> b = [a,a,a]
>>> b
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[1] = 1
>>> b
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
>>>
UPD links I meant references, sorry if little confusing
Say a is some python object. Then [a] * 4 is equivalent to [a, a, a, a]. What this means depends on whether a is mutable or not. Numbers, strings and tuples are not, so if a is one of these kinds of objects (0 in your example), then you get 4 independently changeable copies. Lists, dictionaries and sets are mutable, and in this case you just get 4 references to the same object, in your case the list [0] * 4. Exploiting this knowledge, you'll see that you can do this:
M = [[0] * 4 for i in range(4)]
and get what you want.

Categories

Resources