фильтровать элементы в словаре 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

5 61

5 ответов:

как о дикт понимания:

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}

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

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

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

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

# 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

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

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

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

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

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

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]

вы можете использовать встроенный фильтр для фильтрации словари, списки и т. д. исходя из конкретных условий.

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

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