Подтвердить что ты не робот

Фильтровать элементы в словаре python, где ключи содержат определенную строку

Я кодер C, развивающий что-то в python. Я знаю, как сделать следующее в C (и, следовательно, в C-подобной логике, применяемой к python), но мне интересно, как это сделать Python.

У меня есть словарь d, и я хотел бы работать с подмножеством элементов, только те, у кого ключ (строка) содержит определенную подстроку.

то есть. логика C:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

Я предполагаю, что версия python будет похожа на

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

Я нашел много сообщений о фильтрационных словарях, но не смог найти тот, который был именно таким.

Мой словарь не вложен, и я использую python 2.7

4b9b3361

Ответ 1

Как насчет понятия dict:

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

Как вы видите, он должен быть понятным, поскольку он хорошо читается как английский.

Для этого синтаксиса требуется Python 2.7 или выше.

В Python 3 есть только dict.items(), а не iteritems(), поэтому вы должны использовать:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}

Ответ 2

Пойдите для того, что является наиболее читаемым и легко ремонтируемым. Просто потому, что вы можете записать его в одной строке, это не значит, что вы должны. Ваше существующее решение близко к тому, что я буду использовать, кроме того, что я бы попросил пользователя пропустить поиск значения, и я ненавижу вложенные ifs, если я могу их избежать:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

Однако, если вы realllly хотите что-то позволить вам итерации через фильтрованный dict, то я бы не делал двухэтапный процесс построения отфильтрованного dict, а затем итерации через него, но вместо этого использовал генератор, потому что более pythonic (и удивительный), чем генератор?

Сначала мы создаем наш генератор, и хороший дизайн диктует, что мы делаем его достаточно абстрактным, чтобы его можно было повторно использовать:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

И тогда мы сможем использовать генератор, чтобы решить вашу проблему красиво и чисто с помощью простого, понятного кода:

for key, val in filter_dict(d, some_string):
    # do something

Короче: генераторы являются удивительными.

Ответ 3

input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}

Ответ 4

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

Если вы хотите что-то сделать со значениями словаря, вам не требуется понимание словаря:

Я использую iteritems(), так как вы отметили свой вопрос

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

Теперь результат будет в списке с some_function, примененным к каждой паре ключей/значений словаря, который имеет foo в своем ключе.

Если вы просто хотите иметь дело со значениями и игнорировать ключи, просто измените понимание списка:

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function может быть любым вызываемым, поэтому работала бы лямбда:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

Внутренний список на самом деле не требуется, поскольку вы также можете передать выражение генератора для отображения:

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]