Search a sequence for its minimum and stop as soon as the lowest possible value is found
Antonio Caminero Garcia
tonycamgar at gmail.com
Sun Jan 8 19:45:29 EST 2017
On Friday, January 6, 2017 at 6:04:33 AM UTC-8, Peter Otten wrote:
> Example: you are looking for the minimum absolute value in a series of
> integers. As soon as you encounter the first 0 it's unnecessary extra work
> to check the remaining values, but the builtin min() will continue.
>
> The solution is a minimum function that allows the user to specify a stop
> value:
>
> >>> from itertools import count, chain
> >>> stopmin(chain(reversed(range(10)), count()), key=abs, stop=0)
> 0
>
> How would you implement stopmin()?
>
> Currently I raise an exception in the key function:
>
> class Stop(Exception):
> pass
>
> def stopmin(items, key, stop):
> """
> >>> def g():
> ... for i in reversed(range(10)):
> ... print(10*i)
> ... yield str(i)
> >>> stopmin(g(), key=int, stop=5)
> 90
> 80
> 70
> 60
> 50
> '5'
> """
> def key2(value):
> result = key(value)
> if result <= stop:
> raise Stop(value)
> return result
> try:
> return min(items, key=key2)
> except Stop as stop:
> return stop.args[0]
This is the simplest version I could come up with. I also like the classic 100% imperative, but it seems that is not trendy between the solutions given :D.
you can test it here https://repl.it/FD5A/0
source code:
from itertools import accumulate
# stopmin calculates the greatest lower bound (infimum).
# https://upload.wikimedia.org/wikipedia/commons/0/0a/Infimum_illustration.svg
def takeuntil(pred, seq):
for item in seq:
yield item
if not pred(item):
break
def stopmin(seq, stop=0):
drop_ltstop = (item for item in seq if item >= stop)
min_gen = (min_ for min_ in accumulate(drop_ltstop, func=min))
return list(takeuntil(lambda x: x!= stop, min_gen))[-1]
seq = [1, 4, 7, -8, 0, 7, -8, 9] # 0 just until zero is generated
seq = [1, 4, 7, -8, 7, -8, 9] # 1 the entire sequence is generated
print(stopmin(seq, stop=0))
More information about the Python-list
mailing list