2
\$\begingroup\$

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.

asked Feb 17, 2019 at 2:44
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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)
answered Feb 17, 2019 at 6:26
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.