我有一个看起来像这样的列表:
l1 = ['200:200', '90:728']
我有一本看起来像这样的字典:
d1 = {'200:200':{'foo':'bar'},'300:300':{'foo':'bar'}}
我需要过滤掉只有键在 l1 中的字典。字典应该是这样的:
result = {'200:200':{'foo':'bar'}}
本质上是列表和字典键的交集,同时返回字典的小节。
如果时间对大集合来说是个问题,我如何有效地做到这一点?
谢谢
我有一个看起来像这样的列表:
l1 = ['200:200', '90:728']
我有一本看起来像这样的字典:
d1 = {'200:200':{'foo':'bar'},'300:300':{'foo':'bar'}}
我需要过滤掉只有键在 l1 中的字典。字典应该是这样的:
result = {'200:200':{'foo':'bar'}}
本质上是列表和字典键的交集,同时返回字典的小节。
如果时间对大集合来说是个问题,我如何有效地做到这一点?
谢谢
您可以使用以下代码:
keys = set(l1).intersection(set(d1.keys()))
result = {k:d1[k] for k in keys}
编辑:正如评论者建议的那样,您可以在 Python 2.x 中将第一行替换为:
keys = set(l1).intersection(d1)
在 Python 3.x 中:
keys = d1.keys() & l1
在 3.x 中,这可以很简单:
>>> {k: d1[k] for k in (d1.keys() & l1)}
{'200:200': {'foo': 'bar'}}
在 2.7 下,您可以使用dict.viewkeys()
重新创建此功能:
>>> {k: d1[k] for k in (d1.viewkeys() & l1)}
{'200:200': {'foo': 'bar'}}
在旧版本的 2.x 下,它有点冗长:
>>> {k: d1[k] for k in (set(d1).intersection(l1))}
{'200:200': {'foo': 'bar'}}
不确定每个解决方案的性能,但我会这样做:
{k: v for k, v in d1.items() if k in l1}
您可以在 dict 构造函数中使用列表推导:
result = dict([(k,d1[k]) for k in l1 if k in d1])
如果您担心删除重复键,请先将 l1 设置为一组:
result = dict([(k,d1[k]) for k in set(l1) if k in d1])
定义高效。无论如何,这就是我会做的。如果速度太慢,我可能会将其移至 Cython。
s1 = set(l1)
s2 = set(d1.keys())
s3 = s1 & s2
# now you can access d1 using only keys in s3, or construct a new dict if you like
d2 = dict([(k,d1[k]) for k in s3])
如果内存分配和释放使这个过程花费了太长时间,那么 itertools 可以救命。
import itertools
result = {dict_key:d1[dict_key] for dict_key in itertools.ifilter(lambda list_item: list_item in d1, l1) }
这不会为整个新集合不必要地分配内存,并且 l1 可以很容易地成为迭代器而不是列表。