фильтровать элементы в словаре 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 ответов:
как о дикт понимания:
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.7results = 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()))
преимущество в том, что вы можете использовать его для различных структур данных.