从字典中删除空string的有效方法
我有一个字典,并希望删除所有的空值string的键。
metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)', u'EXIF:CFAPattern2': u''} 做这个的最好方式是什么?
 dict((k, v) for k, v in metadata.iteritems() if v) 
请注意,您的所有密钥都有值。 只是其中一些值是空string。 没有价值的字典中没有这样的关键字; 如果它没有价值,那就不会在字典里。
它可以比BrenBarn的解决scheme更短(我认为更具可读性)
 {k: v for k, v in metadata.items() if v} 
用Python 2.7.3testing。
如果你真的需要修改原来的字典:
 empty_keys = [k for k,v in metadata.iteritems() if not v] for k in empty_keys: del metadata[k] 
请注意,我们必须制作空键的列表,因为我们不能在迭代时修改字典(正如您可能已经注意到的那样)。 尽pipe如此,除了创build一个全新的字典,这种方法的成本更低(记忆方面),除非有很多空值的条目。
如果你想要一个function齐全但简洁的方法来处理经常嵌套的真实世界的数据结构,甚至可以包含循环,我build议从boltons实用程序包中查看重映射实用程序 。
 在pip install boltons或者将iterutils.py复制到你的项目中,只需要: 
 from boltons.iterutils import remap drop_falsey = lambda path, key, value: bool(value) clean = remap(metadata, visit=drop_falsey) 
这个页面有更多的例子,包括从Github的API中处理更多的对象。
它是纯Python,因此它在任何地方都能正常工作,并且已经在Python 2.7和3.3+中进行了全面testing。 最重要的是,我写了这样的案例,所以如果你发现一个案件,它不能处理,你可以bug我修复它在这里 。
BrenBarn的解决scheme是理想的( pythonic ,我可能会添加)。 这是另一个(fp)解决scheme,但是:
 from operator import itemgetter dict(filter(itemgetter(1), metadata.items())) 
基于瑞安的解决scheme ,如果你也有列表和嵌套字典:
 def remove_empty_from_dict(d): if type(d) is dict: return dict((k, remove_empty_from_dict(v)) for k, v in d.iteritems() if v and remove_empty_from_dict(v)) elif type(d) is list: return [remove_empty_from_dict(v) for v in d if v and remove_empty_from_dict(v)] else: return d 
如果你有一个嵌套的字典,并且你希望这个字典甚至可以用于空的子元素,你可以使用BrenBarn的build议的recursion变体:
 def scrub_dict(d): if type(d) is dict: return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v)) else: return d 
 以patriciasz和nneonneo的答案为基础 ,并考虑到你可能想要删除只包含某些falsy的东西(例如'' )而不是其他的东西(比如0 )的可能性,或者你甚至想要包含一些真实的东西(如'SPAM' ),那么你可以做一个非常具体的hitlist: 
 unwanted = ['', u'', None, False, [], 'SPAM'] 
 不幸的是,这不起作用,因为例如0 in unwanted评估为True 。 我们需要区分0和其他的falsy事物,所以我们必须使用的is : 
 any([0 is i for i in unwanted]) 
  …评估为False 。 
 现在用它来del不需要的东西: 
 unwanted_keys = [k for k, v in metadata.items() if any([v is i for i in unwanted])] for k in unwanted_keys: del metadata[k] 
 如果你想要一个新的字典,而不是修改metadata : 
 newdict = {k: v for k, v in metadata.items() if not any([v is i for i in unwanted])} 
快速回答(TL; DR)
Example01
 ### example01 ------------------- mydict = { "alpha":0, "bravo":"0", "charlie":"three", "delta":[], "echo":False, "foxy":"False", "golf":"", "hotel":" ", } newdict = dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(vdata) ]) print newdict ### result01 ------------------- result01 =''' {'foxy': 'False', 'charlie': 'three', 'bravo': '0'} ''' 
详细的答案
问题
- 上下文: Python 2.x
-   scheme:开发人员希望修改字典以排除空白值
- 又名从字典中删除空值
- 又名删除键与空白值
- 又名过滤词典,用于每个键值对上的非空值
 
解
- example01使用python list-comprehension语法和简单的条件来删除“空”值
陷阱
- example01仅在原始字典的副本上运行(不会在原地进行修改)
-   example01可能会产生意想不到的结果,具体取决于开发人员通过“空”
- 开发人员是否意味着保留那些虚伪的价值 ?
- 如果字典中的值不能作为string,开发人员可能会意外丢失数据。
- result01显示从原始集合中只保留了三个键值对
 
替代的例子
- example02有助于处理潜在的隐患
- 该方法是通过改变条件来使用“空”的更精确的定义。
- 这里我们只想过滤出空白string的值。
- 这里我们也使用.strip()过滤掉只包含空格的值。
Example02
 ### example02 ------------------- mydict = { "alpha":0, "bravo":"0", "charlie":"three", "delta":[], "echo":False, "foxy":"False", "golf":"", "hotel":" ", } newdict = dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(str(vdata).strip()) ]) print newdict ### result02 ------------------- result02 =''' {'charlie': 'three', 'echo': False, 'foxy': 'False', 'delta': [], 'bravo': '0', 'alpha': 0 } ''' 
也可以看看
- 列表理解
- falsy
- 检查空string
- 修改原始字典到位
- 词典理解
- 检查空string的缺陷
对于python 3
 dict((k, v) for k, v in metadata.items() if v) 
一些基准:
1.列表理解重新字典
 In [7]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None ...: dic = {k: v for k, v in dic.items() if v is not None} 1000000 loops, best of 7: 375 ns per loop 
2.列表理解使用dict()重新创build字典
 In [8]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None ...: dic = dict((k, v) for k, v in dic.items() if v is not None) 1000000 loops, best of 7: 681 ns per loop 
3.如果v是None,则循环并删除键
 In [10]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None ...: for k, v in dic.items(): ...: if v is None: ...: del dic[k] ...: 10000000 loops, best of 7: 160 ns per loop 
 所以循环和删除在160ns是最快的,列表理解是在〜375ns的一半缓慢,并且对dict()的调用再慢一半〜680ns。 
将3封装到一个函数中会使其重新回到约275ns。 对我来说,PyPy的速度是neet python的两倍。