I'm still pretty new to this website and to python. So, please forgive my question possibly not being specific enough and the possibility of there already being an answer that I haven't found yet.
Basically, I am having trouble with for loops in python.
I want to create lists using the in range() function. Each successive list should set with the next number. For example
[1,2,3,4,5]
[2,3,4,5,6]
[3,4,5,6,7]
I want also the lists that are produced to be of equal length: for example, 5 numbers, 6 numbers or 7 numbers, etc.
l=[]
for i in range (1,10):
for a in range (i):
l.append (i)
print (l[:5])
result is:
[1]
[1, 2]
[1, 2, 2]
[1, 2, 2, 3]
[1, 2, 2, 3, 3]
and then it just repeats with 3. However, I want the next line two start with a new number, so 2 then the next line 3, etc.
I would greatly appreciate your help or at least a hint in the right direction !
If this question has already been answered, I would also appreciate having the link for the respective article.
Start over. Code one or two lines at a time. Print out variables to trace their values. Do not write more code until you know that the current code does what you need. A significant portion of your problem is that you tried to write too much code in one pass, more than you (yet) know how to handle.
Let's start here:
l=[]
for i in range (1,10):
...
Although you clearly state that you want a new starting point at each iteration, you initialize l only once. This means that it will accumulate all of the values you append to it for the entire run of the program, rather than giving you a new list each time.
for a in range (i):
How does this support anything that you're trying to do? You will iterate once, then twice, then 3 times ... what part of your program is repeated in this fashion? You clearly state that you want each list to be of the same length, but then you go out of your way to ensure that you accumulate an ever-increasing list on each completion of this inner loop.
Does this get you moving?
Hey Christopher try this.
for i in range (0,4):
l=[]
for j in range (1+i,6+i):
l.append (j)
print(l)
I think what you're trying to do probably looks something like this:
my_lists = []
for i in range(10):
some_list = []
for j in range(5):
some_list.append(i + j)
print(some_list)
my_lists.append(some_list)
# or if you're being fancy,
# my_lists = [list(range(i, i + 5)) for i in range(10)]
I wouldn't worry too much about the ways to shorten and/or optimise the various
bits of it for now. This gives you a nice list my_lists of all the smaller
lists generated. Does that help you? I'd make sure you understand what's going
on in each loop, and why everything's structured the way it is.
(side note: the sum of the first three values of each list
is given by a fairly straightforward arithmetic progression, so if you need to
calculate it efficiently you'd be better off looking for an algebraic closed
form.)
You could write a function like this one:
def makelists(start, end, n):
sequence = [i for i in range(start, end + 1)]
if n == 1:
print(sequence)
else:
print(sequence)
for i in range(1, n):
sequence = list(map(lambda x: x + 1, sequence))
print(sequence)
makelists(1, 5, 3)
[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
[3, 4, 5, 6, 7]
For other inputs:
makelists(3, 10, 7)
[3, 4, 5, 6, 7, 8, 9, 10]
[4, 5, 6, 7, 8, 9, 10, 11]
[5, 6, 7, 8, 9, 10, 11, 12]
[6, 7, 8, 9, 10, 11, 12, 13]
[7, 8, 9, 10, 11, 12, 13, 14]
[8, 9, 10, 11, 12, 13, 14, 15]
[9, 10, 11, 12, 13, 14, 15, 16]
Related
I am trying to shuffle a list recursively, that has numbers between 1 - 13, such that each number in the even indices will be on the right side of the list and the numbers in the odd indices will be on the left side of the new list.
For example take l=[1, 13, 10, 1, 5, 2, 5, 3].
Function should return: [1, 10, 5, 5, 13, 1, 2, 3].
Here's my work:
def shuffle(arr, start, stop):
if stop == 0:
return [arr[stop-1]]
return [arr[start]] + shuffle(arr, start + 2, stop - 2) + [arr[stop-1]]
Note: start =0 , stop = len(arr). (and surely the length of the array is a power of 2).
My code output is [1, 10, 5, 5, 3, 13, 1, 2, 3], I have been trying for hours to get rid of the extra 3 in the middle, but I'm really having a hard time.
When I wrote the return, I thought about solving a smaller problem, and that's how I usually approach recursive answers, and I am taking the first even number and putting it into the left of the list, then sending the "smaller" list, then putting back the last odd number in the list.
I would really appreciate any help of how to fix this problem, I'm trying to overcome this problem for hours, and I feel like understanding how to fix this will help me understand recursion more.
Thanks in advance.
Edit: Sorry if it wasn't clear but I know how to solve it normally, my goal is to solve it recursively.
Instead of using a start and stop, try using a single index and use negative indexing to traverse the list from the right side:
l=[1, 13, 10, 1, 5, 2, 5, 3]
def shuffle(arr, index=0):
if index >= len(arr):
return []
return [arr[index]] + shuffle(arr, index + 2) + [arr[-1-index]]
print(shuffle(l))
This approach only works for lists with an even number of elements, but that should be ok based on what you've told us.
You could partition the list and only recurse for the shuffling of the left and right portions:
from random import choice
def shuffle(A,left=None,done=0):
if left is None:
A = A[::2]+A[1::2] # partition list
left = len(A[1::2]) # compute left size for recursion
if done>left:return A # all shuffled
if done<left:
rLeft = choice(range(done,left)) # shuffle left part
A[done],A[rLeft] = A[rLeft],A[done]
if left+done<len(A):
rRight = choice(range(left+done,len(A))) # shuffle right part
A[-1-done],A[rRight] = A[rRight],A[-1-done]
return shuffle(A,left,done+1) # recurse
output:
L = [1, 13, 10, 1, 5, 2, 5, 3]
print(shuffle(L))
[10, 5, 5, 1, 2, 1, 3, 13]
Feels much cleaner to me to just create a new list directly:
def shuffle(array):
return array[0::2] + array[1::2]
l = [1, 13, 10, 1, 5, 2, 5, 3]
print(shuffle(l))
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i'm trying to compress a list using generator:
examples
[1, 1, 1, 1, 2, 2, 2, 1, 1, 1] == [1, 2, 1]
[5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0])) == [5, 4, 5, 6, 5, 7, 8, 0]
I tried to use a generator that checks if the 1st and 2nd element are equal then check 2nd and 3rd and so on until it is no longer equal "when it reaches 4" and then yield "5" then it would repeat the process starting with "4"
code
test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0] # sample list
from typing import Iterable
def compress(items: list) -> Iterable:
x = 0
while items[x] == items[x + 1]:
x += 1
yield items[x]
ans = compress(test)
for x in ans:
print(ans)
but i keep getting
generator object compress at 0x00000254D383C820.
why won't it loop?
if i try and use next() it only goes up to 5 and wont check the other numbers.
any assistance is greatly appreciated.
As others have explained, your structure is incorrect - you're only encountering the yield once outside the loop. The ideal way would be to iterate over pairs of consecutive numbers and yield the first one in the loop if they are different.
However, here's a canonical method via itertools.groupby which removes consecutive duplicates:
from itertools import groupby
from operator import itemgetter
list(map(itemgetter(0), groupby(l)))
# [1, 2, 1]
So there are several flaws, all of them described as comments to the question post.
there is a loop missing that would yield more than one value
you print ans and not x, which logically is the generator object.
Is this code working for you?
test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]
def compress(items):
for i, d in enumerate(items[:-1]):
if d == items[i+1]:
continue
yield d
yield items[-1]
for x in compress(test):
print(x)
If you're looking for the same effect as that, look into the itertools.groupby function. It's smarter to use built-in tools.
If you're interested in learning generators, write it. You didn't make any mistakes outside of having "yield" at the wrong level, but you wrote un-Pythonic code. Keeping track of x and x+1 and keeping the whole thing in memory are all bad.
class NeverInList: pass
from typing import Iterable
def compress(items: list) -> Iterable:
previous = NeverInList() # Something never in a list, duh.
for item in items:
if item != previous:
yield item
previous = item
ans = compress(test)
for x in ans:
print(x) # "x", not "ans"
Heh, I recognize this question from somewhere. ;)
I went about it a different way than you but I figured you might find it useful to peep at:
def compress(i:list):
return[i[x]for x in range(len(i))if x==0 or i[x-1]!=i[x]]
The other answers fit the specifics of your question better, I just happened to recognize the setup and figured I'd dig up and offer the solution I gave to this very same problem. Cheers!
One more solution: go through the combination of the list and the same list shifted by one (in other words, by the pairs of consecutive items) and select the second item from each pair where the first (previous) item differs from the second (next) item:
l = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]
[l[0]] + [y for x,y in zip(l, l[1:]) if x!=y]
#[5, 4, 5, 6, 5, 7, 8, 0]
Incidentally, this is one of the fastest solutions presented so far.
you need to implement stack, and see if last element of list is same as value or not
test = [5, 5, 5, 4, 5, 6, 6, 5, 5, 7, 8, 0, 0]
def funct(lis):
l = []
for val in lis:
if len(l) ==0:
l.append(val)
yield val
if l[-1] != val:
l.append(val)
yield val
for result in funct(test):
print(result)
output
5
4
5
6
5
7
8
0
way two, using comparison variable in O(N) time complexity and O(1) space complexity
def funct(lis):
checker = None
for val in lis:
if checker != val:
checker = val
yield val
I have recently created a GUI, which contents tables. User can insert values in cells. As shown figur below.
I want to use values to make some calculation based on values given by user. Rows can be added and removed based on choice of user. with other word, the data I get from user could come from just one row or several rows.
I manage to obtain all values from tables automatically and assign them to python list. Each row gives 5 elements in the list.
I have achieved that. Data in python list have to be processed and organised. This is exactly I want to have help. Because few dags I have been thinking, and I can not figure out, how to continue...
Python data as list from table. as an example.
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '', 11, 12, 13, 14]
What I want to achieve!
I want to split list into 3 times len(data).
I have also achieved this.
def split_seq(seq, num_pieces):
start = 0
for i in range(num_pieces):
stop = start + len(seq[i::num_pieces])
yield seq[start:stop]
start = stop
for data in split_seq(data, int(len(data)/5)):
print(data)
Output would be:
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
['', 11, 12, 13, 14]
The difficulty part starts here.
I want to take each splitted list and throw them into an if condition and store values as variables and message those values to an external function.
Something like this below:
for i in range(len(splitted_list1)):
if splitted_list1[0] == '':
do nothing
else:
x_+str(i)= splitted_list1[i]
externalfunc(x_1,x_2,x_3,x_4,x_5)
for i in range(len(splitted_list2)):
if splitted_list2[0] == '':
do nothing
else:
x_+str(i)= splitted_list2[i]
externalfunc(x_1,x_2,x_3,x_4,x_5)
continues depending on number of splitted_lists
..............
I appreciate any help and you are welcome to come with another idea to come around this.
Use one single list and pass that to externalfunc.
The line x_+str(i)= ... is going to be interpreted as x_"0"= ... or whatever number eventually. The function is going to take in a possibly unknown number of variables. You can just group each "variable" into one list and index them based on the number instead. Which you already have. Each one would be in splitted_list0, splitted_list1, etc.
However, you do not need to asynchronously return the different lists. Instead, you can split the lists and put them in one larger list. This is a two-dimensional array. Seems scary but it's just some lists inside another list.
Now to pass each number to the externalfunc you can use each split list and pass it as an argument. Basically resulting in externalfunc(splitted_list0) and so on.
The final code ends up something like the following:
# Split the data into seperate lists:
split_lists = [data[i*(len(data)/3):(i+1)*(len(data)/3)] for i in range(3)]
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '', 11, 12, 13, 14] becomes
# [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], ['', 11, 12, 13, 14]]
# Pass each list to the external function:
for i in range(split_lists):
externalfunc(split_lists[i])
# split_lists[i] will be [1, 2, 3, 4, 5] or [6, 7, 8, 9, 10], etc.
Note that the 3 in the first line of code can be changed to be any number smaller than the length of the list data. This is just the number of lists to split the data into. Remember to change every 3 if it's hardcoded or just add a variable. Finally, the function externalfunc will have the list of 5 numbers as the first and only argument of the function.
def externalfunc(nums):
for n in nums:
# n = each number in the list
# do something with n, write it somewhere, store it, print it.
print(n)
I understand that given an iterable such as
>>> it = [1, 2, 3, 4, 5, 6, 7, 8, 9]
I can turn it into a list and slice off the ends at arbitrary points with, for example
>>> it[1:-2]
[2, 3, 4, 5, 6, 7]
or reverse it with
>>> it[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]
or combine the two with
>>> it[1:-2][::-1]
[7, 6, 5, 4, 3, 2]
However, trying to accomplish this in a single operation produces in some results that puzzle me:
>>> it[1:-2:-1]
[]
>>>> it[-1:2:-1]
[9, 8, 7, 6, 5, 4]
>>>> it[-2:1:-1]
[8, 7, 6, 5, 4, 3]
Only after much trial and error, do I get what I'm looking for:
>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]
This makes my head hurt (and can't help readers of my code):
>>> it[-3:0:-1] == it[1:-2][::-1]
True
How can I make sense of this? Should I even be pondering such things?
FWYW, my code does a lot of truncating, reversing, and listifying of iterables, and I was looking for something that was faster and clearer (yes, don't laugh) than list(reversed(it[1:-2])).
This is because in a slice like -
list[start:stop:step]
start is inclusive, resultant list starts at index start.
stop is exclusive, that is the resultant list only contains elements till stop - 1 (and not the element at stop).
So for your caseit[1:-2] - the 1 is inclusive , that means the slice result starts at index 1 , whereas the -2 is exclusive , hence the last element of the slice index would be from index -3.
Hence, if you want the reversed of that, you would have to do it[-3:0:-1] - only then -3 would be included in the sliced result, and the sliced result would go upto 1 index.
The important things to understand in your slices are
Start will be included in the slice
Stop will NOT be included in the slice
If you want to slice backwards, the step value should be a negative value.
Basically the range which you specify is a half-open (half-closed) range.
When you say it[-3:0:-1] you are actually starting from the third element from the back, till we reach 0 (not including zero), step one element at a time backwards.
>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]
Instead, you can realize the start value like this
>>> it[len(it)-3 : 0 : -1]
[7, 6, 5, 4, 3, 2]
I think the other two answers disambiguate the usage of slicing and give a clearer image of how its parameters work.
But, since your question also involves readability -- which, let's not forget, is a big factor especially in Python -- I'd like to point out how you can improve it slightly by assigning slice() objects to variables thus removing all those hardcoded : separated numbers.
Your truncate and reverse slice object could, alternatively, be coded with a usage implying name :
rev_slice = slice(-3, 0, -1)
In some other config-like file. You could then use it in its named glory within slicing operations to make this a bit more easy on the eyes :
it[rev_slice] # [7, 6, 5, 4, 3, 2]
This might be a trivial thing to mention, but I think it's probably worth it.
Why not create a function for readability:
def listify(it, start=0, stop=None, rev=False):
if stop is None:
the_list = it[start:]
else:
the_list = it[start:stop]
if rev:
return the_list[::-1]
else:
return the_list
listify(it, start=1, stop=-2) # [2, 3, 4, 5, 6, 7]
listify(it, start=1, stop=-2, rev=True) # [7, 6, 5, 4, 3, 2]
A good way to intuitively understand the Python slicing syntax is to see how it maps to the corresponding C for loop.
A slice like
x[a:b:c]
gives you the same elements as
for (int i = a; i < b; i += c) {
...
}
The special cases are just default values:
a defaults to 0
b defaults to len(x)
c defaults to 1
Plus one more special case:
if c is negative, then a and b are swapped and the < is inverted to a >
How do I create a list and only extract or search out the even numbers in that list?
Create a function even_only(l) that takes a list of integers as its only argument. The
function will return a new list containing all (and only) the elements of l which are evenly divisible by 2. The original list l shall remain unchanged.
For examples, even_only([1, 3, 6, 10, 15, 21, 28]) should return [6, 10, 28], and
even_only([1, 4, 9, 16, 25]) should return [4, 16].
Hint: Start by creating an empty list, and whenever you encounter an even number in it, add it to your list, then at the end, return your list.
"By hand":
def even_only(lst):
evens = []
for number in lst:
if is_even(number):
evens.append(number)
return evens
Pythonic:
def even_only(iter):
return [x for x in iter if is_even(x)]
Since it's homework, you can fill in the is_even function.
Simplest way would be to do what you posted in a comment -- iterate through the input list to find digits evenly divisible by 2, and add them to the return list if so.
The list.append(x) function will help you add an item to a list.
Also as mentioned, look at using the modulo operation to determine if a number is divisible by 2...
The best way to do this (as a beginner) is probably a comprehension list. Since this is a homework, I won't do it for you, but here is the syntax :
[x for x in your_list if (your condition)]
You just have to replace (your condition) with what fits well (basically, exactly what you described).
P.S. I know some people may say comprehension lists are a bit advanced for a beginner, but I think it is not a concept too hard to catch and extremely useful.
>>> a = [1, 3, 6, 10, 15, 21, 28]
>>> b = [i for i in a if i%2 ==0 ]
>>> b
[6, 10, 28]
>>> a
[1, 3, 6, 10, 15, 21, 28]
>>> even_only = lambda seq : [ x for x in seq if str(x)[-1] in "02468" ]
>>> even_only([1, 3, 6, 10, 15, 21, 28])
[6, 10, 28]
Use the filter function to do this in a functional way:
>>> even_filter = lambda x: not x % 2
>>> result = filter(even_filter, [0, 1, 2, 3, 4])
>>> assert result == [0, 2, 4]
Edit: updated with the correct parity of zero per Vincent's comment.
I recently had this issue and used:
list=[1,2,3,4,5,6] #whatever your list is, just a sample
evens=[x for x in list if np.mod(x,2)==0]
print evens
returns [2,4,6]
for every element in list, if element of list modulo is 0 then number is even
initial_list = [1,22,13,41,15,16,87]
even_list = [ x for x in initial_list if x % 2 == 0]
even_list
# [22, 16]
Seems a bit late.But whats given below, works fine for me:
def even_list(*args):
# Returns the even numbers in the list
return [x for x in args if (x % 2 == 0)]
even_list(1,2,3,4,5,6,7,8)
[2, 4, 6, 8]