Вы можете использовать факт 0
, который считается False
, чтобы отфильтровать 0
значения. Затем используйте next
с выражением генератора:
d = {1:0, 2:1, 3:2}
val = min(filter(None, d.values()))
res = next(k for k, v in d.items() if v == val) # 2
Это вернет один ключ в случае дубликатов ключей с 1
в качестве значения. Для нескольких совпадений вы можете использовать понимание списка:
res = [k for k, v in d.items() if v == val]
Обратите внимание, что ваш литерал запрашивает "минимальное ненулевое значение" включает отрицательные значения.
Примечание по производительности
Вышеупомянутое решение является 2-проходным, но имеет временную сложность O ( n ), невозможно иметь меньшую сложность, чем эта. Как показано @Maor, возможно однопроходное решение O ( n ), но оно не обязательно более эффективно:
# Python 3.6.0
%timeit jpp(d) # 43.9 ms per loop
%timeit mao(d) # 98.8 ms per loop
%timeit jon(d) # 183 ms per loop
%timeit reu(d) # 303 ms per loop
Код, используемый для бенчмаркинга:
from random import randint
n = 10**6
d = {i: randint(0, 9) for i in range(n)}
def jpp(d):
val = min(filter(None, d.values()))
return next(k for k, v in d.items() if v == val)
def mao(d):
min_val = None
result = None
for k, v in d.items():
if v and (min_val is None or v < min_val):
min_val = v
result = k
return result
def jon(d):
return min({i for i in d if d[i] != 0})
def reu(d):
no_zeros = {k: v for k, v in d.items() if v != 0}
key, val = min(no_zeros.items(), key=itemgetter(1))
return key