выбор нескольких ключей с условием в Python - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть словарь, содержащий тысячи ключей, вот пример.

Mydict = {'A01': 'value1', 'A02': 'value1', 'C01': 'value1', 'C02': 'value1', 
          'D02': 'value1', 'D03': 'value1', 'D04': 'value1', 'D05': 'value1', 
          'D06': 'value1', 'D07': 'value1', 'D08': 'value1', 'D09': 'value1'}

Я хочу создавать под-словари из условия. Я хочу создать словарь, который начинается с конкретной буквы до. скажем, я хочу 'C' и 'D', но до 'D08'. вот код, который я написал. он выберет все C и D.

NewDict= {x: Mydict[x] for x in Mydict.keys() if x.__contains__('C' or 'D')}

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Вы можете создать set для букв, которые вы хотите сохранить, и еще один для "диапазонов". Затем вы создаете свой словарь, изучая ключ соответствующим образом:

ranges = set(range(9))
letters = {'C', 'D'}

NewDict = {x: Mydict[x] for x in Mydict if x[0] in letters and int(x[1:]) in ranges}

Поскольку проверка членства в set - это O (1) , у вас не должно быть проблем с производительностью, даже если у вас есть тысячи ключей.

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

ranges = {
    'C': set(), # empty set denotes select all 'C'
    'D': set(range(9))
}

NewDict = {x: Mydict[x] for x in Mydict if x[0] in ranges and (len(ranges[x[0]]) == 0 or int(x[1:]) in ranges[x[0]])}

print(NewDict)

выход

{'C01': 'value1', 'C02': 'value1', 'D02': 'value1', 'D03': 'value1', 'D04': 'value1', 'D05': 'value1', 'D06': 'value1', 'D07': 'value1', 'D08': 'value1'}
0 голосов
/ 19 ноября 2018

Выражение 'C' or 'D' превращается в «C», поэтому то, что вы написали, эквивалентно поиску только «C». Вы просто должны разделить свой тест в двух выражениях. Также использование in будет более идиоматичным, чем использование __contains__

{x: Mydict[x] for x in Mydict.keys() if 'C' in x or 'D' in x}

Если вы хотите применить тест к каждому ключу в списке, например, проверьте, что он меньше, чем «D08», просто сделайте это и используйте лексикографический порядок.

NewDict= {x: Mydict[x] for x in Mydict.keys() if x < 'D08'}

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

NewDict= {x: Mydict[x] for x in Mydict.keys() if 'C01' < x < 'D08'}

Используйте включающий <= или исключительный < оператор сравнения в зависимости от того, что вы хотите.

Для более сложных условий на ключах, вероятно, яснее использовать явную функцию, такую ​​как:

def condition(key):
    return 'C01' < key < 'D08'

NewDict= {x: Mydict[x] for x in Mydict.keys() if condition(x)}

С таким форматом вы можете сделать тест на ключе настолько сложным, насколько захотите, и результат останется легко читаемым.

Было бы идиоматичнее и короче использовать items() для итерации как по ключам, так и по значениям, таким как:

NewDict= {k: v for k,v in Mydict.items() if 'C01' < k < 'D08'}

В качестве последнего слова переменные падежа Camel обычно зарезервированы для классов в python. Для переменных общепринятым условием было бы использовать случай змеи, например new_dict.

0 голосов
/ 19 ноября 2018

Вам, по крайней мере, нужно обновление:

Mydict = {'A01': 'value1', 'A02': 'value1', 'C01': 'value1', 'C02': 'value1', 
          'D02': 'value1', 'D03': 'value1', 'D04': 'value1', 'D05': 'value1', 
          'D06': 'value1', 'D07': 'value1', 'D08': 'value1', 'D09': 'value1'}
NewDict= {x: Mydict[x] for x in Mydict.keys() if x.__contains__('D')
         }
NewDict.update({x: Mydict[x] for x in Mydict.keys() if x.__contains__('C')
         })
NewDict

Однако, вероятно, есть более эффективный способ сделать это ...

Также имена переменных Python должны быть в случае змеинапример, new_dict

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