Подтвердить что ты не робот

Python: найти ближайший ключ в словаре от данного ключа ввода

У меня есть данные в виде словаря. NOw Я беру данные от пользователя, и это может быть что угодно.. И я пытаюсь сделать следующее. Если ключ существует, тогда cool... выберите значение из словаря. если нет, то выберите ближайший (в цифровом смысле). Например, если входной ключ равен 200 и клавиши такие как:....

197,202,208...

Тогда, вероятно, 202 является ближайшим ключом к 200.. Теперь, с точки зрения алгоритма. его прямо вперед.. но есть ли питонический способ сделать это? Благодаря

4b9b3361

Ответ 1

здесь ваша функция в одной строке:

data.get(num, data[min(data.keys(), key=lambda k: abs(k-num))])

edit: чтобы не оценивать min, когда ключ находится в использовании dict:

data[num] if num in data else data[min(data.keys(), key=lambda k: abs(k-num))]

или если все значения в data оцениваются до True, вы можете использовать:

data.get(num) or data[min(data.keys(), key=lambda k: abs(k-num))]

Ответ 2

Эта проблема намного сложнее, чем клавиши dict, не имеющие особого порядка. Если вы можете играть с тем, как вы делаете dict, чтобы они были в порядке (например, ваш пример) и использовали python >= 2.7, вы можете использовать OrderedDict и bisect, чтобы сделать это молниеносно.

import collections
a = collections.OrderedDict()
for i in range(100):
    a[i] = i

import bisect
ind = bisect.bisect_left(a.keys(), 45.3)

Тогда вам нужно только проверить элемент ind и ind-1, чтобы увидеть, что ближе, тем самым делая намного меньше вычислений.


Как указано ниже, Стивен G, в Python3,.keys() - это не просто список и его необходимо изменить на один.

bisect.bisect_left(list(a.keys()), 45.3)

Ответ 3

Вместо использования OrderedDict и bisect рассмотрите тип SortedDict в модуле sortedcontainers, Это версия pure-Python и fast-as-C отсортированного списка, dict и заданных типов со 100% -ным охватом тестирования и часами стресса.

С помощью SortedDict вы можете делить пополам нужную клавишу. Например:

from sortedcontainers import SortedDict
sd = SortedDict((key, value) for key, value in data)

# Bisect for the index of the desired key.
index = sd.bisect(200)

# With that index, lookup the key.
key = sd.iloc[index]

# You can also look ahead or behind to find the nearest key.
behind = sd.iloc[index - 1]
ahead = sd.iloc[index + 1]

Это Pythonic для использования PyPI!

Ответ 4

Если все, что у вас есть, это словарь Python, вы не можете сделать лучше, чем проверка всех записей в словаре (как в ответе "Ответ" ). Однако, если вы хотите найти ближайший ключ более эффективно, чем это (т.е. В O(log N) вместо O(N)), вам нужно какое-то сбалансированное дерево.

К сожалению, я не считаю, что Python имеет такую ​​структуру данных в своей стандартной библиотеке, что и Pythonic - это использовать вместо этого dict. Итак, если вы ожидаете сделать много таких запросов на большой карте, лучшим выбором может быть поиск библиотеки расширений или даже сворачивание собственного...

Ответ 5

Это должно делать то, что вы хотите (минус получить его от ключа, но вы можете понять это:).

f = lambda a,l:min(l,key=lambda x:abs(x-a))
numbers = (100, 200, 300, 400)
num = int(raw_input())
print 'closest match:', f(num, numbers)

Примечание: f находится в этом вопросе.