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])
Related
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I have a nested list containing nothing but 0's, defined by a size of 5 by 5, and I want to be able to set specific values int he nested list to 1 using direct indexing. This is the solution I currently have:
Grid = [[0] * 5] * 5
ObX = 2
print(ObX)
ObY = 3
print(ObY)
Grid[ObY][ObX] = 1
print(Grid)
Expected output:
2
3
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]]
Actual Output:
2
3
[[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]]
As far as I can tell, it's ignoring the "ObY" index and just deciding that it wants to replace every value in each list at index "ObX". What am I doing wrong?
The list of lists you created contains the same list 5 times, changing it once changes all of its copies
In [1]: Grid = [[0] * 5] * 5
In [2]: [id(x) for x in Grid]
Out[2]:
[140392398718848,
140392398718848,
140392398718848,
140392398718848,
140392398718848]
Use this to create 5 different lists
In [5]: Grid =[[0]*5 for _ in range(5)]
In [6]: [id(x) for x in Grid]
Out[6]:
[140392397938112,
140392396267776,
140392397478656,
140392398276224,
140392398427200]
I'm trying to produce all permutations of a certain number of numbers (for example, 0s and 1s) for a variable number of positions. I will call the number of numbers ord (e.g. ord=2 for only 0s and 1s; ord=3 for 0s, 1s, and 2s) and the number of positions Num. Hence the number of permutations is ord**Num.
Note: I don't want to use itertools or any other types of built-in functions. I'm asking this out of curiosity, not just trying to find a solution.
For ord=2 and Num=3, the output, in any order, should be:
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
This can be accomplished by:
ord = 2
mylist = []
for a in range(ord):
for b in range(ord):
for c in range(ord):
mylist.append([a,b,c])
For ord = 2 and Num = 4, the output should be:
[[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]]
But then I would have to add another nested for loop:
ord = 2
mylist = []
for a in range(ord):
for b in range(ord):
for c in range(ord):
for d in range(ord):
mylist.append([a,b,c,d])
An obvious solution is to add 0s and 1s randomly to a list of length Num and then to accept that list if it hasn't already been added to mylist, but I want a solution that isn't quite so ridiculous.
This is the closest I've gotten so far to a real solution:
def myperms(elem, mylist):
for i in range(len(elem)-1,-1,-1):
while (elem[i] + 1) < ord:
elem = list(elem)
elem[i] += 1
if elem not in mylist:
mylist.append(elem)
if (elem[i] + 1) >= ord:
elem = list(elem)
elem[i] = 0
return mylist
Num = 3
ord = 2
TotsNum = ord**Num
mylist = []
elem = [0,]*Num
mylist.append(elem)
print(myperms(elem, mylist))
But this only gives:
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0]]
I've tried calling the function within itself (recursion), but I haven't been able to figure out how to do it properly. Does anyone have any ideas about how to solve it recursively? Thank you!
Let's use a recursive solution:
def get_seq(ord, num):
val = [0]*num
N = num
def recurse(ord, num):
for i in range(ord):
val[N - num] = i
if num > 1:
yield from recurse(ord, num-1)
else:
yield val[:]
return recurse(ord, num)
print(list(get_seq(2, 4)))
Output:
[[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]]
For other inputs:
>>> list(get_seq(3, 2))
[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
Use binary, which consists of 0s and 1s.
n = 4
all_permutations = []
for i in range(2**n):
permutation = []
string = bin(i)
string = string.split("0b")[1]
while len(string) != n:
string = f"0{string}"
for i in string:
permutation.append(int(i))
all_permutations.append(permutation)
print(all_permutations)
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
I´m a begginer in Python and I want to remove a specific item from a list, the removal criterion is that when an item contains the three firsts elements null it must be removed from the main list. This is what I´m trying to do:
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
temp = []
for i in range(len(a)):
for j in range(len(a[i])):
if a[j][0] + a[j][1] + a[j][2] == 0:
temp = a.pop(j)
print temp
else:
print a
j += 1
i += 1
And I´m getting the following error:
if a[j][0] + a[j][1] + a[j][2] == 0:
IndexError: list index out of range
I have no idea what I´m doing wrong...
Thanks!
You could use a list comprehension to filter out sublists
>>> a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
>>> a = [i for i in a if any(i[:3])]
>>> a
[[0, 0, 1, 1], [1, 1, 1, 1]]
This basically works by using slicing to get elements [0] through [2], then uses any to check whether there are non-zero values.
All you need is this (range in this case is unnecessary):
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
newList = []
for i in a:
if i[0] + i[1] + i[2] != 0:
newList.append(i)
print newList
if you want to avoid the any() method call you can just use a conditional check with the in operator.
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
b = [i for i in a if 1 in i[:3]]
# [[0, 0, 1, 1], [1, 1, 1, 1]]
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