Reputation: 497
I want to run this loop over a list basically it searches for a number in my a range till it finds it search for the next number in the following iterations but instead it starts over again
This is my code
z = [30,84,126,135,137,179,242,342,426]
c=[]
for m in z:
for i in range(1,1002, 7):
if m in range(i, i+7):
c.append(m%7)
break
elif m not in range(i, i+7):
c.append(0)
print len(c) # outputs 246
but len(c) should be equal to 143, how do I fix this?
Upvotes: 0
Views: 101
Reputation: 3706
while a generator
seemed to answer the question, there is a better tool for the programming problem: itertools.groupby
from itertools import groupby
z = [1,2,3, 30,84,126,135,136,137,140,141,179,242,342,426]
g = dict([[k, [*g]] for k, g in groupby(z, key=lambda x: (x-1)//7)])
d = [((tuple(g[i]) if len(g[i]) > 1 else g[i][0]) if (i in g) else 0)
for i in range(0, 143)]
ran against my 1st answer's code: (do use the same z
, it has been changed)
c == d
Out[278]: True
see how well matched itertools.groupby
is look at the dict wrapped groupby result:
g
Out[279]:
{0: [1, 2, 3],
4: [30],
11: [84],
17: [126],
19: [135, 136, 137, 140],
20: [141],
25: [179],
34: [242],
48: [342],
60: [426]}
(the above works in 3.6, the [*g]
and dictionary key
test (i in g)
may be different in 2.7)
Upvotes: 1
Reputation: 3706
perhaps what you want is a generator
https://docs.python.org/2/howto/functional.html#generator-expressions-and-list-comprehensions
z = [30,84,126,135,136,137,179,242,342,426]
c = []
def counter(maximum, inc): # resetable generator from doc example
i = 1
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += inc
ig = counter(1002, 7)
for m in z:
for i in ig:
# catch multiple nums in same range
if m < i:
clast = c.pop()
# inline if-else inside append converts int to tuple to add m to
c.append((clast if type(clast) == tuple else (clast,)) + (m,))
# reset ig count
ig.send(i - 7)
break
if i <= m < i+7:
c.append(m)
break
else:
c.append(0)
# exhaust ig if you really want full count = 143
for i in ig:
c.append(0)
print(len(c))
added catching nums in same interval, needed the resettable generator
fixed up the last 2 issues I know of: now makes a flat tuple for multiple nums in a single range counts correctly by resetting ig to i - 7
Upvotes: 1
Reputation: 336
I think I figured out what you're trying to do, and your best bet is to change how you're incrementing your search range.
z = [30,84,126,135,137,179,242,342,426]
c=[] # initialize results array
i = 1 # initialize i
for m in z: # for each item in list
while 1: # perform this action until loop breaks
if m in range(i, i+7): #if m is in range
c.append(m%7)
break #break the while loop, moving on to the next item
elif m not in range(i, i+7):
c.append(0)
i = i+7 #increment the search range, but do not break the loop
#Display results
print len(c)
print c
So in your original code, you reset the search range i
for each element in the array z
. This is why your len(c)
values are getting so much higher than expected. In my code, I only iterate i from 1 to 1002 a single time as I go through the array of values.
Please let me know if this doesn't solve your issue, I was able to match the functionality you described but not the expected output for len(c)
. If you want to get the expected value, you can change the code to match this:
z = [30,84,126,135,137,179,242,342,426]
c=[] # initialize results array
i = 1 # initialize i
for m in z: # for each item in list
while i<1002: # perform this action until loop breaks
if m in range(i, i+7): #if m is in range
c.append(m%7)
i = i+7
break # break the while loop, moving on to the next item
elif m in range(i-7, i):
break
else:
c.append(0)
i = i+7 # increment the search range, but do not break the loop
while i<1002: # finish iterating i all the way up to 1002
c.append(0)
i = i+7
#Display results
print len(c)
print c
Which gets a len(c)
of 143.
Upvotes: 1