Answers:
Python 2.X
dict((k, v) for k, v in metadata.iteritems() if v)
Python 2.7-3.X
{k: v for k, v in metadata.items() if v is not None}
请注意,您所有的键都有值。只是其中一些值是空字符串。没有值的字典中就没有键。如果它没有价值,就不会在字典中。
.items()
。
{k: v for k, v in metadata.items() if v is not None}
... if v!=None
像这样使用: {k: v for k, v in metadata.items() if v!=None}
BrenBarn的解决方案是理想的(我可能会添加pythonic)。但是,这是另一个(fp)解决方案:
from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
如果您想要一种功能全面但简洁的方法来处理通常是嵌套的甚至可能包含循环的现实世界数据结构,建议您从boltons实用程序包中查看remap实用程序。
之后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+中进行了全面测试。最棒的是,我是针对这种情况编写的,因此,如果您发现它无法处理的情况,可以在这里麻烦我进行修复。
基于Ryan的解决方案,如果您还有列表和嵌套字典:
对于Python 2:
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
对于Python 3:
def remove_empty_from_dict(d):
if type(d) is dict:
return dict((k, remove_empty_from_dict(v)) for k, v in d.items() 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
d = { "things": [{ "name": "" }] }
如果您有一个嵌套的字典,并且希望它甚至对空的子元素也适用,则可以使用BrenBarn建议的递归变体:
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
items()
代替iteritems()
Python 3
### 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'}
'''
### 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 ='''
{'alpha': 0,
'bravo': '0',
'charlie': 'three',
'delta': [],
'echo': False,
'foxy': 'False'
}
'''
对于python 3
dict((k, v) for k, v in metadata.items() if v)
以patriciasz和nneonneo的答案为基础,并考虑到您可能希望删除仅包含某些虚假内容(例如''
)但没有其他虚假内容(例如)的密钥的可能性0
,或者您甚至想包含一些真实的内容(例如'SPAM'
) ,那么您可以制作一个非常具体的命中列表:
unwanted = ['', u'', None, False, [], 'SPAM']
不幸的是,这并不是很有效,因为例如0 in unwanted
计算结果为True
。我们需要区分0
和其他虚假的东西,所以我们必须使用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])}
[]
我阅读了该线程中的所有答复,并且也引用了该线程: 使用递归函数删除嵌套字典中的空字典
我最初在这里使用解决方案,效果很好:
尝试1:太热(不具有性能或过时的能力):
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
但是在Python 2.7世界中提出了一些性能和兼容性问题:
isinstance
代替type
for
循环中以提高效率items
而不是iteritems
尝试2:太冷(缺乏记忆):
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v,dict):
v = scrub_dict(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
DOH!这不是递归的,也不是完全的记忆。
尝试3:正确(到目前为止):
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v,dict):
v = scrub_dict(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
if isinstance(v, list):
使用原始scrub_dict(d)
实现清理列表。 @staticmethod
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v, dict):
v = scrub_dict(v)
if isinstance(v, list):
v = scrub_list(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
@staticmethod
def scrub_list(d):
scrubbed_list = []
for i in d:
if isinstance(i, dict):
i = scrub_dict(i)
scrubbed_list.append(i)
return scrubbed_list
您可以执行此操作的另一种方法是使用字典理解。这应该与2.7+
result = {
key: value for key, value in
{"foo": "bar", "lorem": None}.items()
if value
}
如果您使用的是以下选项pandas
:
import pandas as pd
d = dict.fromkeys(['a', 'b', 'c', 'd'])
d['b'] = 'not null'
d['c'] = '' # empty string
print(d)
# convert `dict` to `Series` and replace any blank strings with `None`;
# use the `.dropna()` method and
# then convert back to a `dict`
d_ = pd.Series(d).replace('', None).dropna().to_dict()
print(d_)
上面提到的某些方法会忽略是否存在整数,并且会以0和0.0的值进行浮点运算
如果有人想避免上述情况,可以使用以下代码(从嵌套字典和嵌套列表中删除空字符串和None值):
def remove_empty_from_dict(d):
if type(d) is dict:
_temp = {}
for k,v in d.items():
if v == None or v == "":
pass
elif type(v) is int or type(v) is float:
_temp[k] = remove_empty_from_dict(v)
elif (v or remove_empty_from_dict(v)):
_temp[k] = remove_empty_from_dict(v)
return _temp
elif type(d) is list:
return [remove_empty_from_dict(v) for v in d if( (str(v).strip() or str(remove_empty_from_dict(v)).strip()) and (v != None or remove_empty_from_dict(v) != None))]
else:
return d
“由于我目前还为使用Python编写一个桌面应用程序,因此我在数据输入应用程序中发现有很多条目,而其中一些条目不是强制性的,因此用户可以将其留空,以进行验证,因此很容易抓住。所有条目,然后丢弃空键或字典的值,因此我的代码上方显示了如何使用字典理解功能轻松地将它们取出,并保留不为空的字典值元素。我使用Python 3.8.3
data = {'':'', '20':'', '50':'', '100':'1.1', '200':'1.2'}
dic = {key:value for key,value in data.items() if value != ''}
print(dic)
{'100': '1.1', '200': '1.2'}
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
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
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的两倍。
list(dic.items())
在py 3中调用。对于低的Null /空值比率,del似乎仍然更快。我想建立该列表与重新创建字典一样,对内存消耗同样有害。