Как получить минимальное значение между лимитами? - PullRequest
1 голос
/ 27 мая 2020

Введение в проблему

У меня есть список чисел, и я хочу, учитывая определенное значение, получить ближайшее значение в списке, которое удовлетворяет условию. Это: разница между ближайшим значением и самим значением должна быть меньше 0,5

Что я сделал

Я новичок в лямбда-выражениях, так что, возможно, я не понимаю рабочий процесс этой функции. Я основал (скопировал) свой код на этом ответе: из списка целых чисел, получить число, наиболее близкое к заданному значению

def min_in_limits(value,list):
    new_val = min(list, key=lambda x: float(abs(float(x)-float(value)))<0.5)
    return new_val

Итак, когда я даю эти входные данные:

list = [9,11,13]
value = 8.9

Функция min_in_limits возвращает 11 вместо 9

При пошаговой оценке лямбда возвращает:

True, False, False

Почему это не удается?

Менее элегантно , но функциональный

def less_elegant(value,list):
    dictionary = {}
    for i in list:
        temp = float(abs(float(i)-float(value)))
        if temp < 0.5:
            dictionary.update({temp:i})
    keys = dictionary.keys()
    return(dictionary[min(keys)])

Спасибо!

Ответы [ 4 ]

2 голосов
/ 27 мая 2020

key в min используется для переназначения значений при их сравнении. Текущее значение передается функции, заданной как key, и ее выходные данные используются при сравнении объектов вместо исходных объектов. Если вы добавите < 0.5 к этой функции, вместо расстояния в виде числа, вы вернете только логический флаг, который сообщает вам, если ваш номер близок к .

Что вы могли используйте вместо этого:

def min_in_limits(value, list_):
    value = float(value)  # if it is e.g. string
    new_val = min(list_, key=lambda x: abs(float(x) - value))
    if abs(new_val - value) < 0.5:
        return new_val
    return None

После того, как вы найдете свой минимум, проверьте, находится ли он в пределах вашего порогового значения 0.5 и верните None, если это не так, что означает, что значение в list_ не близко достаточно. Вместо жесткого кодирования 0.5 вы можете передать его как аргумент функции.

Вы должны передать value, что равно float, и list_, которое представляет собой список float s или int s, и в этом случае вы можете удалить value = float(value) и заменить float(x) только x.

Кроме того, пожалуйста, не используйте ключевые слова (например, list) в качестве имен переменных / параметров.

1 голос
/ 27 мая 2020

В дополнение к @ ответ Луки и поскольку вы использовали dict.update в for l oop, вы также можете использовать понимание словаря для выполнения той же операции при необходимости:

def min_in_limits(value, li):
    value = float(value)
    d = {abs(i - value): i for i in li if abs(i - value) < 0.5}
    # `d` might be an empty dict
    return d[min(d.keys())] if d else None
1 голос
/ 27 мая 2020

Есть один лайнер, который вы можете использовать. Предполагая, что l=[9, 11, 13] и v=8.9, вы можете использовать следующее:

min(map(lambda x: x if float(abs(float(x) - float(v))) < 0.5 else float('inf'), l))

Здесь мы сопоставляем все значения l, которые не удовлетворяют нашему условию, на бесконечность. Затем мы берем наименьшее значение, используя функцию min.

0 голосов
/ 27 мая 2020

Есть много способов написать функции, но я могу кратко объяснить, почему ваши исходные коды терпят неудачу, если вам интересно:

def min_in_limits(value,list):
    new_val = min(list, key=lambda x: float(abs(float(x)-float(value)))<0.5)
    return new_val

Ваша лямбда-функция в порядке, но обратите внимание, что когда вы применяете min (data =, key =), ключевой аргумент внутри позволяет вам настроить, в каком logi c вы хотите, чтобы ваши данные были отсортированы (прочтите здесь ). Поскольку ваша лямбда-функция возвращает список со значением [True, False, False], применение min к [True, False, False] возвращает последний элемент False в массиве, который соответствует значению = 11.

Вы можете проверить bahaviour из min() себя, просто:

a=min(True,False,False)
b=max(True,False,False)
print (a,b)

дает вам:

False True
...