I am trying to print out numbers by increasing positive and negative values around a center number, and I don't think I've found the best way. For example, say I want to find what number in a list my center value is closest to. I do that by adding one, see if it matches, then subtracting one from the original number and see if that matches, then add two from the original number and so on. I know there are other ways of finding the closest match but I'm not looking for that - I'm looking for the best way to print out numbers steadily getting farther from a center value. Here's my code:
def inc_val(center, i, neg_toggle):
mult = 1
if neg_toggle:
neg_toggle = False
mult = -1
else:
neg_toggle = True
mult = 1
i += 1
val = center + (i * mult)
return val, i, neg_toggle
i = 0
center = 24
val = center
neg_toggle = False
my_set = {30, 50, 90}
while val not in my_set:
print(val)
val, i, neg_toggle = inc_val(center, i, neg_toggle)
This prints out the following list, as desired:
24
25
23
26
22
27
21
28
20
29
19
To be clear, I'm interested in the incrementing numbers. The while not in my_set
part is just to illustrate. I am not intentionally trying to re-invent anything, so if there's a built-in or simpler way to do this, please let me know.
1 Answer 1
Rather than maintaining the state of the iteration using three variables val
, i
, and neg_toggle
, it would be more elegant to write a generator. Then, the state of the iteration would be maintained by the flow of the execution of the generator itself.
def zoom_out(center):
decr = center
incr = center + 1
while True:
yield decr
decr -= 1
yield incr
incr += 1
for n in zoom_out(24):
if n in (30, 50, 90):
break
print(n)
Furthermore, fancy iteration can often be expressed more elegantly using itertools
. Here, I'd take advantage of itertools.count()
to implement the generator, and itertools.takewhile()
to detect when to stop executing the infinite generator.
from itertools import count, takewhile
def zoom_out(center):
decr = count(center, -1)
incr = count(center + 1)
while True:
yield next(decr)
yield next(incr)
for n in takewhile(lambda n: n not in (30, 50, 90), zoom_out(24)):
print(n)