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)) -- https://mail.python.org/mailman/listinfo/python-list