Я программист 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
python
python-2.7
dictionary
filtering
памятка
источник
источник
Ответы:
Как насчет понимания слов :
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}
источник
filtered_dict = {k:d[k] for k in d if filter_string in k}
?d[k]
поиска.# do something
в комментариях, но здесь мы опускаем несколько ключей.iteritems
в Python 3? Я так не думаю. Итак, моя версия будет совместима, не так ли?iteritems
наitems
, что аналогично Python 2.7iteritems
.Выбирайте то, что наиболее читается и легко обслуживается. То, что вы можете записать это в одну строку, не означает, что вы должны это делать. Ваше существующее решение близко к тому, что я бы использовал, кроме того, что я бы использовал iteritems, чтобы пропустить поиск значений, и я ненавижу вложенные if, если я могу их избежать:
for key, val in d.iteritems(): if filter_string not in key: continue # do something
Однако, если вы действительно хотите, чтобы что-то позволяло вам перебирать отфильтрованный dict, я бы не стал выполнять двухэтапный процесс построения отфильтрованного dict и затем повторять его, а вместо этого использовал бы генератор, потому что это более питоническое (и потрясающее), чем генератор?
Сначала мы создаем наш генератор, и хороший дизайн требует, чтобы мы сделали его достаточно абстрактным, чтобы его можно было использовать повторно:
# 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
Короче: генераторы классные.
источник
Вы можете использовать встроенную функцию фильтра для фильтрации словарей, списков и т. Д. На основе определенных условий.
filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))
Преимущество в том, что вы можете использовать его для разных структур данных.
источник
items:
должно бытьitem:
в определении лямбда.input = {"A":"a", "B":"b", "C":"c"} output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
источник
iteritems()
будет более эффективным, чемitems()
.items()
, который действует как Python 2.7iteritems
.Джонатон в своем ответе предложил вам подход, основанный на понимании диктовки . Вот подход, который касается вашей работы .
Если вы хотите что-то сделать со значениями словаря, вам вообще не нужно понимание словаря:
Я использую
iteritems(
), поскольку вы отметили свой вопроспитон-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]
источник
map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
- это даст вам[4]
.map
является понимание списка.[f(v) for k, v in d.iteritems() if substring in k]
Я думаю, что это намного удобнее и эффективнее.results = list(starmap(...))
илиfor result in starmap(...): ...
).