Related
It could be very easy question but i can't make it through this question. For example if n = 5, i want the answer list = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]. If n = 6, i want the answer list = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6]
The below code is what i made first time, but i even wonder this format is right to use.
rules = []
rules.extend([x for x in range(n)])
if i use this kind of code, it only makes list = [1, 2, 3, 4, 5 ...... , n] Should i change the x format to another things?
rules = []
rules.extend([[x] * x for x in range(n)])
or if i use this kind of code, it makes list in the list format like this, list = [[1], [2], [2], [3], [3], [3]]
Use can use a nested list comprehension:
>>> n = 5
>>> rules = [i for i in range(1, n + 1) for __ in range(i)]
>>> rules
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
This question already has answers here:
Removing from a list while iterating over it [duplicate]
(5 answers)
Closed 4 years ago.
[First-ever question from first-ever Stack-o-flow Python beginner user]
I have been trying to create a function that appends numbers 1 to 10 and then erase from 10 to 1 in python list object.
I succeeded however, I bumped into a weird behavior of for-in loops.
Below is what I did & succeeded:
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
for n in range(1,11):
li.remove(li[-1])
print(li)
a()
would print:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
[]
However, if I change the second part of its for-loop range(1,11) to li, the iteration stops as shown below.
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
for n in li: <-------------- THIS PART
li.remove(li[-1])
print(li)
a()
Would print:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
So, I checked its length of the object li.
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
print("Length before passed: ", len(li))
for n in li: <------------ THIS
print("Length BEFORE REMOVE: ", len(li))
li.remove(li[-1])
print("Length AFTER REMOVE: ", len(li))
print(li)
a()
Would print:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Length before passed: 10
Length BEFORE REMOVE: 10
Length AFTER REMOVE: 9
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Length BEFORE REMOVE: 9
Length AFTER REMOVE: 8
[1, 2, 3, 4, 5, 6, 7, 8]
Length BEFORE REMOVE: 8
Length AFTER REMOVE: 7
[1, 2, 3, 4, 5, 6, 7]
Length BEFORE REMOVE: 7
Length AFTER REMOVE: 6
[1, 2, 3, 4, 5, 6]
Length BEFORE REMOVE: 6
Length AFTER REMOVE: 5
[1, 2, 3, 4, 5] <---- And it stops here.
What is going on here?
Why would python for-loop stop before its full cycle?
Thank you very much.
In your case, the iteration stops because you're iterating from the start, but you're removing elements from the end at the same time:
The 1st iteration ends with 9 elements, so the loop proceeds to the 2nd element.
The 2nd iteration ends with 8 elements, so the loop proceeds to the 3rd element
...
The 5th iteration ends with 5 elements, and there's no 6th element to proceed to and the loop ends.
This is why mutating a list while iterating it is generally inadvisable.
Try running this, you'll understand immediately
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
for n in li:
print(n)
li.remove(li[-1])
print(li)
a()
By removing elements this happens:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
[1, 2, 3, 4, 5, 6, 7, 8, 9]
2
[1, 2, 3, 4, 5, 6, 7, 8]
3
[1, 2, 3, 4, 5, 6, 7]
4
[1, 2, 3, 4, 5, 6]
5
[1, 2, 3, 4, 5]
You add then print 10 times, you remove then print 10 times - simplified:
a = []
a.append(1)
print(a) # [1]
a.pop()
print(a) # []
You start with an empty list and print after adding - you stop with an empty list and print.
The problem with the second code part is: you are modifying an iterable while iterating - that is generally a bad idea.
If you change:
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
while(li):
li.pop() # same but easier - removes last element without params
if(li): # test if non empty
print(li)
or optimized:
for _ in range(len(li)-1): # one less so it stops bevore removing the last elem
li.pop()
print(li)
you get the desired output.
It's cause you are iterating the list from the start to the end and you are always removing the last element. As remove method alter the list and the for-in loop from python consider this alterations, you iterate over the five first itens and remove the five last ones.
My sugestion is do something like this:
def a():
li = []
for i in range(1,11):
li.append(i)
print(li)
print("Length before passed: ", len(li))
# Remove the last item while has items
while len(li):
li.pop()
Similiar questions to this one have been asked before, but none exactly like it an and I'm kind of lost.
If I have 2 sets of lists (or a lists of lists)
listOLists = [[1,2,3],[1,3,2]]
listOLists2 = [[4,5,6],[4,6,5]]
And I want 'merge' the two lists to make
mergedLists = [[1,2,3,4,5,6],[1,3,2,4,5,6],[1,2,3,4,6,5],[1,3,2,4,6,5]]
How would I do this?
list1s=[[1,2,3],[3,2,1],[2,2,2]]
list2s=[[3,3,3],[4,4,4],[5,5,5]]
for indis1 in list1s:
for indis2 in list2s:
print(indis1 + indis2)
try and;
[1, 2, 3, 3, 3, 3]
[1, 2, 3, 4, 4, 4]
[1, 2, 3, 5, 5, 5]
[3, 2, 1, 3, 3, 3]
[3, 2, 1, 4, 4, 4]
[3, 2, 1, 5, 5, 5]
[2, 2, 2, 3, 3, 3]
[2, 2, 2, 4, 4, 4]
[2, 2, 2, 5, 5, 5]
You may use generator to simplify your code, like this:
a = [[1, 2, 3], [1, 3, 2], [2, 1, 3]]
b = [[4, 5, 6], [4, 6, 5], [5, 4, 6]]
c = [i + j for i in a for j in b]
print c
Output:
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 6, 5], [1, 2, 3, 5, 4, 6], [1, 3, 2, 4, 5, 6], [1, 3, 2, 4, 6, 5], [1, 3, 2, 5, 4, 6], [2, 1, 3, 4, 5, 6], [2, 1, 3, 4, 6, 5], [2, 1, 3, 5, 4, 6]]
list1 = [[1,2,3],[1,3,2]]
list2 = [[4,5,6],[4,6,5]]
mergedLists = []
for list1_inner in list1:
for list2_inner in list2:
mergedLists.append(list1_inner + list2_inner)
print(mergedLists)
A comparison of methods:
import itertools
import random
l1 = [[random.randint(1,100) for _ in range(100)]for _ in range(100)]
l2 = [[random.randint(1,100) for _ in range(100)]for _ in range(100)]
With itertools:
def itert(l1, l2):
[list(itertools.chain(*x)) for x in itertools.product(l1, l2)]
With for loops:
def forloops(list1, list2):
mergedLists = []
for list1_inner in list1:
for list2_inner in list2:
mergedLists.append(list1_inner + list2_inner)
With a simple Comprehension:
def comp(l1, l2):
[i + j for i in l1 for j in l2]
Speed
%time itert(l1, l2)
Wall time: 99.8 ms
%time comp(l1, l2)
Wall time: 31.3 ms
%time forloops(l1, l2)
Wall time: 46.9 ms
How do you extract a value out of n of a list in python ?
For example :
n = 3
l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
And I would like to get
[0, 3, 6, 9]
I know I can do this with a for, but is there any more pythonic and short way ?
You can do a simple list comprehension
>>> n = 3
>>> l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [i for i in l if i%n==0]
[0, 3, 6, 9]
If your list is always like that, then you can use strides
>>> l[::3]
[0, 3, 6, 9]
Tip
Use range to generate lists like that
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Using slicing would be the most pythonic way:
In [1]: n = 3
In [2]: l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: l[::n]
Out[3]: [0, 3, 6, 9]
Use a slice with stride:
l[::n]
Demo:
>>> n = 3
>>> l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[::n]
[0, 3, 6, 9]
print l[::3] # slice with step n = 3
x = []
for i in l[0::3]:
x.append(i)
for j in l[1::3]:
x.append(j)
for k in l[2::3]:
x.append(k)
print(x)
I want to take a random list like
[1, 2, 3, 4, 5, 6, 7]
that would return
[1, 4, 7, 2, 5, 4, 7]
but for a list of any number. is there a way to increase the start by 1 ?
Using list comprehension:
>>> xs = [1, 2, 3, 4, 5, 6, 7]
>>> [x for i in range(3) for x in xs[i::3]]
[1, 4, 7, 2, 5, 3, 6]