我是一名 C 程序员,正在用 Python 开发一些东西。我知道如何在 C 中执行以下操作(因此在应用于 python 的类似 C 的逻辑中),但我想知道“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
filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}
如果你看到它,它应该是不言自明的,因为它读起来很像英语。
此语法需要 Python 2.7 或更高版本。
dict.items()
,而不是 iteritems()
,所以你可以使用:
filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}
选择最具可读性和最容易维护的东西。仅仅因为您可以将其写在一行中并不意味着您应该这样做。您现有的解决方案与我使用的解决方案接近,除了我会使用 iteritems 来跳过值查找,并且如果我可以避免嵌套 if,我讨厌嵌套 if:
for key, val in d.iteritems():
if filter_string not in key:
continue
# do something
但是,如果你真的想要一些东西让你迭代过滤的字典,那么我不会执行构建过滤的字典然后迭代它的两步过程,而是使用生成器,因为更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
简而言之:发电机非常棒。
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
您可以使用内置函数“filter()”:
data = {'aaa':12, 'bbb':23, 'ccc':8, 'ddd':34}
# filter by key
print(dict(filter(lambda e:e[0]=='bbb', data.items() ) ) )
# filter by value
print(dict(filter(lambda e:e[1]>18, data.items() ) ) )
输出:
{'bbb':23}
{'bbb':23, 'ddd':34}
乔纳森在他的回答中为您提供了一种使用字典理解的方法。这是一种处理“做某事”部分的方法。 如果你想用字典的值做一些事情,你根本不需要字典理解:
我正在使用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
可以是任何可调用的,因此 lambda 也可以工作:
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]