Python находит ближайшее десятичное соответствие - PullRequest
0 голосов
/ 28 марта 2011

У меня есть следующий список:

CHOICES = (
    ('8.25', '0'),
    ('7.35', '1'),
    [...]
)

Используемая мной модель сохраняет первое значение в кортеже (например, 8,25 - случайно, в мм).Мне нужна функция, которая принимает любое заданное десятичное значение (возможно, отсутствует в списке) и сопоставляет его с ближайшим значением в списке CHOICES, чтобы вернуть соответствующее целое число.

Таким образом, пример ввода может быть 8.11который возвратил бы 0 или 7.30, который возвратил бы 1 и т. д.

Ответы [ 3 ]

4 голосов
/ 28 марта 2011

Если ваши значения не отсортированы и предполагается, что количество вариантов невелико:

result = sorted([(math.abs(k - input_val),v) for (k,v) in choices])[0]

В противном случае сортируйте варианты один раз и используйте двоичный поиск ( bisect ), как предложено в другом ответе. Это будет выглядеть так:

#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))
2 голосов
/ 28 марта 2011

http://docs.python.org/library/bisect.html

Прочитайте примеры в конце.

0 голосов
/ 28 марта 2011

Это работает очень хорошо

distances = [ (abs(target-float(v)), m) for v,m in CHOICES ]
value, match = min( distances )

Поскольку вы используете слово «десятичный», возможно, вы имеете в виду это.

distances = [ (abs(target-decimal.Decimal(v)), m) for v,m in CHOICES ]

Не то, чтобы это имело большое значение.

...