I have a list as follows:
CHOICES = (
('8.25', '0'),
('7.35', '1'),
[...]
)
The model I use stores the first value in the tuple (e.g. 8.25 -incidentally, in mm). I need a function that takes any given decimal value (potentially not in the list) and matches it with the closest value on the CHOICES list, to return the relevant whole number.
So example input could be 8.11
which would return 0
or 7.30
which would r开发者_StackOverfloweturn 1
etc.
Unless your values are sorted and assuming the number of the choices is not huge:
result = sorted([(math.abs(k - input_val),v) for (k,v) in choices])[0]
Otherwise sort the choices once and use binary search (bisect), as suggested in other answer. It'd look like:
#do this part only once
choices_dict = dict(choices)
sorted_keys = sorted([ float(k) for (k,v) in choices])
#...
l,r = bisect_left(input_value,sorted_keys), bisect_right(input_value,sorted_keys)
k = l if math.abs(input_value-l)<math.abs(input_value-r) else r
result = choices_dict(str(k))
http://docs.python.org/library/bisect.html
Read the examples at the end.
This works pretty well
distances = [ (abs(target-float(v)), m) for v,m in CHOICES ]
value, match = min( distances )
Since you use the word, "decimal", perhaps you mean this.
distances = [ (abs(target-decimal.Decimal(v)), m) for v,m in CHOICES ]
Not that it matters much.
精彩评论