我有一个字典,里面有一大堆词条。我只对其中的几个感兴趣。有什么简单的方法可以把其他的都剪掉吗?
当前回答
简式:
[s.pop(k) for k in list(s.keys()) if k not in keep]
正如大多数答案所建议的那样,为了保持简洁,我们必须创建一个重复的对象,无论是list还是dict。这个函数创建了一个丢弃列表,但删除了原始字典中的键。
其他回答
我们可以这样简单地处理函数:
>>> dict_filter = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
>>> large_dict = {"a":1,"b":2,"c":3,"d":4}
>>> new_dict_keys = ("c","d")
>>> small_dict=dict_filter(large_dict, new_dict_keys)
>>> print(small_dict)
{'c': 3, 'd': 4}
>>>
在我看来,这是最简单的方法:
d1 = {'a':1, 'b':2, 'c':3}
d2 = {k:v for k,v in d1.items() if k in ['a','c']}
我也喜欢这样做来揭示价值观:
a, c = {k:v for k,v in d1.items() if k in ['a','c']}.values()
下面是python 2.6中的一个例子:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
过滤部分是if语句。
如果你只想选择很多键中的几个,这个方法比delnan的答案要慢。
根据问题的标题,人们会期望在适当的地方过滤字典-几个答案建议了这样做的方法-仍然不明显的一个明显的方法是什么-我添加了一些时间:
import random
import timeit
import collections
repeat = 3
numbers = 10000
setup = ''
def timer(statement, msg='', _setup=None):
print(msg, min(
timeit.Timer(statement, setup=_setup or setup).repeat(
repeat, numbers)))
timer('pass', 'Empty statement')
dsize = 1000
d = dict.fromkeys(range(dsize))
keep_keys = set(random.sample(range(dsize), 500))
drop_keys = set(random.sample(range(dsize), 500))
def _time_filter_dict():
"""filter a dict"""
global setup
setup = r"""from __main__ import dsize, collections, drop_keys, \
keep_keys, random"""
timer('d = dict.fromkeys(range(dsize));'
'collections.deque((d.pop(k) for k in drop_keys), maxlen=0)',
"pop inplace - exhaust iterator")
timer('d = dict.fromkeys(range(dsize));'
'drop_keys = [k for k in d if k not in keep_keys];'
'collections.deque('
'(d.pop(k) for k in list(d) if k not in keep_keys), maxlen=0)',
"pop inplace - exhaust iterator (drop_keys)")
timer('d = dict.fromkeys(range(dsize));'
'list(d.pop(k) for k in drop_keys)',
"pop inplace - create list")
timer('d = dict.fromkeys(range(dsize));'
'drop_keys = [k for k in d if k not in keep_keys];'
'list(d.pop(k) for k in drop_keys)',
"pop inplace - create list (drop_keys)")
timer('d = dict.fromkeys(range(dsize))\n'
'for k in drop_keys: del d[k]', "del inplace")
timer('d = dict.fromkeys(range(dsize));'
'drop_keys = [k for k in d if k not in keep_keys]\n'
'for k in drop_keys: del d[k]', "del inplace (drop_keys)")
timer("""d = dict.fromkeys(range(dsize))
{k:v for k,v in d.items() if k in keep_keys}""", "copy dict comprehension")
timer("""keep_keys=random.sample(range(dsize), 5)
d = dict.fromkeys(range(dsize))
{k:v for k,v in d.items() if k in keep_keys}""",
"copy dict comprehension - small keep_keys")
if __name__ == '__main__':
_time_filter_dict()
结果:
Empty statement 8.375600000000427e-05
pop inplace - exhaust iterator 1.046749841
pop inplace - exhaust iterator (drop_keys) 1.830537424
pop inplace - create list 1.1531293939999987
pop inplace - create list (drop_keys) 1.4512304149999995
del inplace 0.8008298079999996
del inplace (drop_keys) 1.1573763689999979
copy dict comprehension 1.1982901489999982
copy dict comprehension - small keep_keys 1.4407784069999998
因此,如果我们想要在适当的地方更新,似乎del是赢家-字典理解解决方案取决于正在创建的字典的大小,当然,删除一半的键已经太慢了-所以避免创建一个新的字典,如果你可以在适当的地方过滤。
编辑来解决@mpen的评论-我从keep_keys中计算了drop key(假设我们没有drop key) -我假设keep_keys/drop_keys是这个迭代的集合,或者会花很长时间。有了这些假设,del仍然更快——但要确定的是:如果你有一个(set, list, tuple)的下拉键,使用del
我们也可以通过稍微更优雅的字典理解来实现这一点:
my_dict = {"a":1,"b":2,"c":3,"d":4}
filtdict = {k: v for k, v in my_dict.items() if k.startswith('a')}
print(filtdict)
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录