Найти минимальное ненулевое значение в словаре (Python) - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть словарь, и я хотел бы получить ключ, значение которого является минимальным ненулевым значением.

например. с учетом ввода:

{1:0, 2:1, 3:2}

Будет возвращено 2.

Ответы [ 5 ]

0 голосов
/ 04 сентября 2018

Решение

some_dict = {1:0, 2:1, 3:2}
compare = []

for k, v in some_dict.items():
    if k != 0:
        compare.append(k)

x = min(compare)

print(x)

Я просто appended все ненулевые keys до list (compare) и затем применяется min(compare)

Мы можем подключить x обратно и проверить, что он указывает на ключ 1, который является наименьшим ненулевым key, и возвращает value, который 0

>>> print(some_dict[x]) 
>>> 0
0 голосов
/ 04 сентября 2018
print(min(i for i in dictionary if  dictionary[i] != 0))

это делает набор без нулей и возвращает минимальное значение в этом наборе. Хотя стоит отметить, что это делает 2 итерации и, следовательно, медленнее, чем решение Маора Рафаэли.

0 голосов
/ 04 сентября 2018

Предполагая, что dict назван a:

from operator import itemgetter

a = {1:0, 2:1, 3:2}
# remove zeros
no_zeros = {k: v for k, v in a.items() if v != 0} # can use `if v`
# find minimal key and value (by value)
key, val = min(no_zeros.items(), key=itemgetter(1))
# key = 2, val = 1
0 голосов
/ 04 сентября 2018

Вы можете сделать это на одну итерацию.

d = {1:0, 2:1, 3:2}

# Save the minimum value and the key that belongs to it as we go
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

print(result)

Некоторые предположения:

  • Будут учитываться отрицательные значения
  • Он вернет первый ключ , который нашел
  • Если это поможет, min_val будет содержать минимальное значение
0 голосов
/ 04 сентября 2018

Вы можете использовать факт 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
...