Python 过滤字典以仅包含某些键?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3420122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:58:38  来源:igfitidea点击:

Filter dict to contain only certain keys?

pythondictionary

提问by mpen

I've got a dictthat has a whole bunch of entries. I'm only interested in a select few of them. Is there an easy way to prune all the other ones out?

我有一个dict有一大堆条目的。我只对其中的几个感兴趣。有没有简单的方法来修剪所有其他的?

采纳答案by jnnnnn

Constructing a new dict:

构建一个新的字典:

dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }

Uses dictionary comprehension.

使用字典理解。

If you use a version which lacks them (ie Python 2.6 and earlier), make it dict((your_key, old_dict[your_key]) for ...). It's the same, though uglier.

如果您使用缺少它们的版本(即 Python 2.6 及更早版本),请将其设为dict((your_key, old_dict[your_key]) for ...). 它是一样的,虽然更丑陋。

Note that this, unlike jnnnnn's version, has stable performance (depends only on number of your_keys) for old_dicts of any size. Both in terms of speed and memory. Since this is a generator expression, it processes one item at a time, and it doesn't looks through all items of old_dict.

请注意,与 jnnnnn 的版本不同,这对于old_dict任何大小的 s都具有稳定的性能(仅取决于 your_keys 的数量)。无论是速度还是内存。由于这是一个生成器表达式,它一次处理一项,并且不会查看 old_dict 的所有项。

Removing everything in-place:

就地删除所有内容:

unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]

回答by jnnnnn

Here's an example in python 2.6:

这是python 2.6中的一个例子:

>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}

The filtering part is the ifstatement.

过滤部分是if语句。

This method is slower than delnan's answer if you only want to select a few of very many keys.

如果您只想选择非常多的几个键,则此方法比 delnan 的答案慢。

回答by Kai

Given your original dictionary origand the set of entries that you're interested in keys:

鉴于您的原始字典orig和您感兴趣的条目集keys

filtered = dict(zip(keys, [orig[k] for k in keys]))

which isn't as nice as delnan's answer, but should work in every Python version of interest. It is, however, fragile to each element of keysexisting in your original dictionary.

这不像 delnan 的答案那么好,但应该适用于每个感兴趣的 Python 版本。但是,它对于keys原始字典中存在的每个元素都是脆弱的。

回答by MyGGaN

Based on the accepted answer by delnan.

基于 delnan 接受的答案。

What if one of your wanted keys aren't in the old_dict? The delnan solution will throw a KeyError exception that you can catch. If that's not what you need maybe you want to:

如果您想要的密钥之一不在 old_dict 中怎么办?delnan 解决方案将抛出一个您可以捕获的 KeyError 异常。如果这不是您所需要的,也许您想:

  1. only include keys that excists both in the old_dict and your set of wanted_keys.

    old_dict = {'name':"Foobar", 'baz':42}
    wanted_keys = ['name', 'age']
    new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
    
    >>> new_dict
    {'name': 'Foobar'}
    
  2. have a default value for keys that's not set in old_dict.

    default = None
    new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
    
    >>> new_dict
    {'age': None, 'name': 'Foobar'}
    
  1. 只包括在 old_dict 和您的通缉键集中都存在的键。

    old_dict = {'name':"Foobar", 'baz':42}
    wanted_keys = ['name', 'age']
    new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
    
    >>> new_dict
    {'name': 'Foobar'}
    
  2. 没有在 old_dict 中设置的键有一个默认值。

    default = None
    new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
    
    >>> new_dict
    {'age': None, 'name': 'Foobar'}
    

回答by Ryan

This function will do the trick:

这个函数可以解决这个问题:

def include_keys(dictionary, keys):
    """Filters a dict by only including certain keys."""
    key_set = set(keys) & set(dictionary.keys())
    return {key: dictionary[key] for key in key_set}

Just like delnan's version, this one uses dictionary comprehension and has stable performance for large dictionaries (dependent only on the number of keys you permit, and not the total number of keys in the dictionary).

就像delnan的版本一样,这个使用字典理解,对于大型字典有稳定的性能(只取决于你允许的键数,而不是字典中键的总数)。

And just like MyGGan's version, this one allows your list of keys to include keys that may not exist in the dictionary.

就像 MyGGan 的版本一样,这个版本允许您的键列表包含字典中可能不存在的键。

And as a bonus, here's the inverse, where you can create a dictionary by excluding certain keys in the original:

作为奖励,这是相反的,您可以通过排除原始中的某些键来创建字典:

def exclude_keys(dictionary, keys):
    """Filters a dict by excluding certain keys."""
    key_set = set(dictionary.keys()) - set(keys)
    return {key: dictionary[key] for key in key_set}

Note that unlike delnan's version, the operation is not done in place, so the performance is related to the number of keys in the dictionary. However, the advantage of this is that the function will not modify the dictionary provided.

注意,和delnan的版本不同,操作没有到位,所以性能和字典中key的个数有关。但是,这样做的好处是该函数不会修改提供的字典。

Edit:Added a separate function for excluding certain keys from a dict.

编辑:添加了一个单独的功能,用于从字典中排除某些键。

回答by Jim

This one liner lambda should work:

这个线性 lambda 应该可以工作:

dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])

Here's an example:

下面是一个例子:

my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")

# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}

It's a basic list comprehension iterating over your dict keys (i in x) and outputs a list of tuple (key,value) pairs if the key lives in your desired key list (y). A dict() wraps the whole thing to output as a dict object.

这是一个基本的列表推导式迭代您的 dict 键(i 在 x 中)并输出一个元组(键,值)对列表,如果键位于您想要的键列表 (y) 中。dict() 将整个内容包装为 dict 对象输出。

回答by ransford

Slightly more elegant dict comprehension:

稍微更优雅的字典理解:

foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}

回答by Suor

You can do that with projectfunction from my funcylibrary:

您可以使用我的funcy库中的项目函数来做到这一点

from funcy import project
small_dict = project(big_dict, keys)

Also take a look at select_keys.

另请查看select_keys

回答by Y.Y

Code 1:

代码 1:

dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
    if key % 2 == 0:
        d1[key] = value

Code 2:

代码 2:

dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}

Code 3:

代码 3:

dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}

All pieced of code performance are measured with timeit using number=1000, and collected 1000 times for each piece of code.

所有分片的代码性能都是用timeit用number=1000来衡量的,每段代码采集1000次。

enter image description here

在此处输入图片说明

For python 3.6 the performance of three ways of filter dict keys almost the same. For python 2.7 code 3 is slightly faster.

对于python 3.6,三种过滤字典键的方式的性能几乎相同。对于 python 2.7,代码 3 稍微快一些。

回答by nehem

Short form:

简写:

[s.pop(k) for k in list(s.keys()) if k not in keep]

As most of the answers suggest in order to maintain the conciseness we have to create a duplicate object be it a listor dict. This one creates a throw-away listbut deletes the keys in original dict.

正如大多数答案所暗示的那样,为了保持简洁,我们必须创建一个重复的对象,无论是 alist还是dict。这个创建了一个一次性list但删除了 original 中的键dict