获取Python词典的子集


73

我有一本字典:

{'key1':1, 'key2':2, 'key3':3}

我需要将该词典的子集传递给第三方代码。它只想要一个包含键的字典['key1', 'key2', 'key99'],如果它得到另一个键(例如'key3'),它就会陷入混乱之中。有问题的代码不在我的控制范围内,所以我留在必须清理字典的位置。

将字典限制为一组键的最佳方法是什么?

给定示例字典和上面允许的键,我想要:

{'key1':1, 'key2':2}

Answers:


77
In [38]: adict={'key1':1, 'key2':2, 'key3':3}
In [41]: dict((k,adict[k]) for k in ('key1','key2','key99') if k in adict)
Out[41]: {'key1': 1, 'key2': 2}

在Python3(或Python2.7或更高版本)中,您也可以使用dict-comprehension做到这一点:

>>> {k:adict[k] for k in ('key1','key2','key99') if k in adict}
{'key2': 2, 'key1': 1}

9
Dict理解也在Python 2.7中。
摩根·哈里斯

我希望有一个操作员。喜欢adict - {'key1'} == {'key2':2, 'key3':3}
wim 2014年

似乎是没有理智的逆dict.update方法
WIM

3
{k:v表示k,v表示adict.items(),如果('key1','key2','key99')}中的k也可以正常工作。只是略有不同。
jlimahaverford

1
为了让事情变得更简单考虑{k: v for k, v in adict.items() if k in new_keys}{k:adict[k] for k in new_keys if k in adict}。如果new_keys大,我们在后一种情况下是否不会遇到类似的问题?
jlimahaverford


9

在现代Python(2.7 +,3.0 +)中,使用字典理解:

d = {'key1':1, 'key2':2, 'key3':3}
included_keys = ['key1', 'key2', 'key99']

{k:v for k,v in d.items() if k in included_keys}

如果我正确理解的话,这可能会降低效率len(d) >> len(included_keys)>>表示“更大”)。但我想通常情况下len(d)不会很大...
Oren Milman


3

我的方法是。

from operator import itemgetter

def subdict(d, ks):
    return dict(zip(ks, itemgetter(*ks)(d)))

my_dict = {'key1':1, 'key2':2, 'key3':3}

subdict(my_dict, ['key1', 'key3'])

更新资料

但是,我不得不承认,当的长度ks为0或1时,上述实现无法处理这种情况。下面的代码处理了这种情况,不再是单行代码。

def subdict(d, ks):
    vals = []
    if len(ks) >= 1:
        vals = itemgetter(*ks)(d)
        if len(ks) == 1:
            vals = [vals]
    return dict(zip(ks, vals))

我经常from operator import itemgetter as ig会节省一些水平线空间和打字。我想我没有记得itemgetter要提取多个项目。伟大的提醒,谢谢!
MrDrFenner

0

复杂类Myclass是的子类collections.UserDict。要选择它的一个子集,即保留其所有容器属性,可以方便地定义一个方法,例如这样命名sub

def sub(self, keys):
    subset = Myclass() # no arguments; works if defined with only keyword arguments
    for key in keys:
        subset[key] = self[key]
    return subset

然后用作Myclass.sub([key1, key2 ...]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.