Вызов ближайшего словарного ключа меньше заданного значения - PullRequest
0 голосов
/ 10 июля 2019

У меня есть словарь со значениями времени в качестве ключей, и мне нужно получить значение, связанное с этими ключами.Природа моей программы означает, что я почти никогда не смогу вызвать словарь с точным, существующим ключом, поэтому я хочу сделать следующее: я хочу передать случайное входное значение в словарь и для словарячтобы найти ключ, который находится ближе всего, НО меньше, чем входное значение, а затем дайте мне значение, связанное с этим ключом.

До сих пор я пробовал лямбда-выражение, которое должно найти ближайший ключ ниже, чемввод, но когда я выполняю его, я обнаруживаю, что он не дает мне ожидаемого значения.Поскольку мой настоящий код довольно длинный и сложный, я создал небольшую тестовую программу для более четкого наблюдения за своими результатами:

import random as r

my_dict = {0.0: 0, 1.0: 1, 2.0: 2, 3.0: 3, 4.0: 4, 5.0: 5}

value = round(r.uniform(0, 5), 1)
print('Random Value is: ' + str(value))

dict_value = my_dict[min(my_dict, key=lambda x:abs(x-value))]
print('Corresponding Dictionary Value is: ' + str(dict_value))

Эта программа успешно генерирует случайное значение с плавающей запятой, округленное до одного десятичного знака.Когда он передает его в лямбда-функцию, он не дает точного значения в ответ.Например, если случайное значение равно 7,7, соответствующее значение словаря возвращает 3 (что неверно), случайное значение 3,1 возвращает 3 (это правильно), 4,7 возвращает 5 (неправильно) и т. Д. Я могу понять, почемуэто происходит, так как я вычитаю свое значение из x, которое сравнило бы разницу двух чисел с каждым ключом.Также нет ничего, что указывало бы, что ближайший ключ должен быть ниже, чем ввод, только чтобы найти ближайший ключ к вводу в целом, но я не уверен, как это реализовать.Я надеюсь, что я был ясен, но, пожалуйста, задавайте вопросы, если нет.Спасибо!

Ответы [ 3 ]

0 голосов
/ 10 июля 2019
import random

my_dict = {0.0: 0, 1.0: 1, 2.0: 2, 3.0: 3, 4.0: 4, 5.0: 5}
rand_num = round(random.uniform(0, 5), 1)

# This will find the dict key that corresponds to the value you are seeking
index = min(my_dict, key=lambda n: abs(n-value))

# Then just grab the value from the dict
print(my_dict[index])

Если вы решите использовать другую структуру данных, этот метод все равно будет работать со списком:

keys = [1.0, 2.0, 3.0]
value = 1.2
target = min(keys, key=lambda n: abs(n-value))
print(target)

Кроме того, вы можете отфильтровать все ключи в словаре, которые больше, чем заданное значение:

value = 2.2
valid_keys = [key for key in my_dict if key <= value]
target_key = max(valid_keys)
answer = my_dict[target_key]

Вы также можете использовать функцию фильтра:

value = 1.6
filtered_keys = filter(lambda x: x <= value, my_dict))
target_key = max(filtered_keys)
answer = my_dict[target_key]

Обновление: примеры фильтрации здесь найдут только ближайший ключ, который МЕНЬШЕ, чем заданное значение, что не совсем то, что вы просили. Я оставлю здесь примеры для тех, кто в будущем будет искать этот вопрос, который им может пригодиться. Для вашего конкретного случая использования используйте первый пример.

0 голосов
/ 10 июля 2019

Вы можете использовать модуль bisect и создать собственный контейнер - с помощью collections.abc:

from collections.abc import Mapping
import bisect

class closest_dict(Mapping):
    def __init__(self, items):
        s = [*sorted(items)]
        self._keys = [i[0] for i in s]
        self._items = [i[1] for i in s]

    def __getitem__(self, key):
        idx = bisect.bisect_left(self._keys, key)

        if idx > len(self._keys) - 1:
            return self._items[-1]

        if abs(self._keys[idx-1] - key) < abs(self._keys[idx] - key):
            return self._items[idx-1]

        return self._items[idx]

    def __iter__(self):
        yield from self._keys

    def __len__(self):
        return len(self._keys)

my_dict = {0.0: 0, 1.0: 1, 2.0: 2, 3.0: 3, 4.0: 4, 5.0: 5}

d = closest_dict( (k, v) for k, v in my_dict.items() )

for val in [-1.0, 0.0, 0.1, 2.1, 6.0]:
    print('Closest value to key {} is {}'.format(val, d[val]))

Печать:

Closest value to key -1.0 is 0
Closest value to key 0.0 is 0
Closest value to key 0.1 is 0
Closest value to key 2.1 is 2
Closest value to key 6.0 is 5
0 голосов
/ 10 июля 2019

Если для вашего контекста требуются структуры данных, которые вы представили, вы можете попробовать что-то вроде (диктовать понимание для исключения значений, которые слишком велики):

import random as r

my_dict = {0.0: 0, 1.0: 1, 2.0: 2, 3.0: 3, 4.0: 4, 5.0: 5}

value = round(r.uniform(0, 5), 1)
print('Random Value is: ' + str(value))

new_dict = {k:v for (k,v) in my_dict.items() if v<value}
dict_value = my_dict[min(new_dict, key=lambda x:abs(x-value))]
print('Corresponding Dictionary Value is: ' + str(dict_value))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...