Как напечатать только ключевые значения словаря для определенного диапазона на основе значений словаря? - PullRequest
2 голосов
/ 27 июня 2019

Предположим, у меня есть словарь в следующем формате.

new_dict = {'worry': [23, 667, 1692, 1940], 'win': [96, 200, 286], 'work': [833, 1458]}

Я хочу напечатать только ключи key только на основе значений от 0 до 100.

Выводв этом случае:

{'беспокойство', 'победа}}

Я пытался:

dict0100 = {k:v for (k,v) in new_dict.items() if new_dict.values(range(100))}

Я получаю ошибку, как значенияпринять только 1 аргумент.

Примечание: значения варьируются от 0 до 5000 в моем случае.Мне нужны только ключевые значения от 0 до 100.

Любая помощь приветствуется.

Ответы [ 5 ]

2 голосов
/ 27 июня 2019

Попробуйте это:

dict0100 = {k: v for (k, v) in new_dict.items() if any(i <= 100 for i in v)}

Если вы хотите, чтобы список тоже был отфильтрован:

dict0100 = {k: l for k, l in [(k, [i for i in v if i <= 100]) for k, v in new_dict.items()] if l}

Примечание о < или range

Об использовании оператора сравнения < или выражения in range() я бы лично пошел на x < 100, поскольку здесь все элементы списков называются натуральными числами, а сравнение более производительно:

import timeit

t1 = timeit.timeit(lambda: 3 in range(100))
print(t1) # 0.37976

t2 = timeit.timeit(lambda: 3 <= 100)
print(t2) # 0.08725
2 голосов
/ 27 июня 2019

Я бы использовал проверку диапазона с any.Вот аккуратная функция генератора многократного использования:

def get_keys_in_range(dct, lo=0, hi=100):
    rng = range(lo, hi) 
    for key, lst in dct.items():
        if any(l in rng for l in lst):
            yield key

[*get_keys_in_range(new_dict, lo=0, hi=100)]
# ['worry', 'win']

Стоит отметить, что проверки членства на range объектах имеют постоянное время (O (1)) в python-3.x (ноO (N) в python-2.x, поэтому вы можете рассмотреть другие решения, используя чистые сравнения).

Обратите внимание, что диапазон закрыт в нужном интервале, что означает, что вы хотите сделать range(lo, hi+1), если вы хотите, чтобы верхняя граница была включающей.


Это можно сократить до

lo, hi = 0, 100
[key for key, lst in new_dict.items() if any(l in range(lo, hi) for l in lst)]
# ['worry', 'win']

Вы можете предварительно кэшировать range для немного большей производительности (каксделано внутри функции).

rng = range(lo, hi)
[key for key, lst in new_dict.items() if any(l in rng for l in lst)]
# ['worry', 'win']
1 голос
/ 27 июня 2019

ваш диктант имеет ключи типа str и значения типа list (of ints)

ожидаемый результат - объект set (а не dict).

попробуйте это:

new_dict = {'worry': [23, 667, 1692, 1940], 'win': [96, 200, 286], 'work': [833, 1458]}

set0100 = {k for k, arr in new_dict.items() if any(v in range(100) for v in arr)}

print(set0100)

это использует тот замечательный факт, что range объекты реализуют метод __contains__, который позволяет нам использовать in для них.

1 голос
/ 27 июня 2019

Попробуйте:

dict0100 = {k:v for (k,v) in new_dict.items() if [x for x in v if all([x<100,x>0])]}

Это сохранит и ключ, и значение, для ключа удаляется только ": v"

0 голосов
/ 27 июня 2019

dict0100 = {k:v for (k,v) in new_dict.items() if all([v_e < 5000 for v_e in v])}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...