在 Python 中使用 None 值删除字典中键的正确方法
Posted
技术标签:
【中文标题】在 Python 中使用 None 值删除字典中键的正确方法【英文标题】:Proper way to remove keys in dictionary with None values in Python 【发布时间】:2016-02-21 04:42:30 【问题描述】:在 Python 中从值 == None
的字典中删除键的正确方法是什么?
【问题讨论】:
您必须澄清您的意思,因为字典中的每个键都必须有一个值,即使该值是''
或 0
或 None
。
k: v for k, v in original.items() if v is not None
【参考方案1】:
通常,您将通过过滤旧的dict
来创建一个新的dict
。字典推导非常适合这种事情:
k: v for k, v in original.items() if v is not None
如果你必须更新原来的dict,你可以这样做...
filtered = k: v for k, v in original.items() if v is not None
original.clear()
original.update(filtered)
这可能是我能想到的最“干净”的就地删除它们的方法(在迭代时修改 dict 是不安全的)
在python2.x上使用original.iteritems()
【讨论】:
目前,此问题的其他两个答案似乎在从字典中删除时迭代字典。是你在最后一句中提到的吗?迭代dict.keys
或 dict.items
?
@RobertL -- 是的。如果您要在此过程中更改字典,则迭代 dict
总是不安全的。在 python2.x 上迭代 dict.keys()
和 dict.items()
很好,但在 python3.x 上不安全。例如,请参阅***.com/a/6777632/748858。
感谢您使用 Python 3 语法进行更新。随着 Python 2 变老,这个答案变得越来越笨拙。也许是时候先提供 Python 3+ 的答案,并将遗留语法作为脚注。
@JasonR.Coombs -- 同意。我把这个改成默认为 python3.x —— 实际上这也可以在 python2.x 上工作,只是效率稍低。
如果您有嵌套字典,这似乎不起作用【参考方案2】:
如果您需要递归删除 None 值,最好使用这个:
def delete_none(_dict):
"""Delete None values recursively from all of the dictionaries"""
for key, value in list(_dict.items()):
if isinstance(value, dict):
delete_none(value)
elif value is None:
del _dict[key]
elif isinstance(value, list):
for v_i in value:
if isinstance(v_i, dict):
delete_none(v_i)
return _dict
根据@dave-cz 的建议,添加了支持列表类型值的功能。
@mandragor 添加了额外的 if 语句以允许包含简单列表的字典。
如果您需要从字典、列表、元组、集合中删除所有 None 值,这也是一种解决方案:
def delete_none(_dict):
"""Delete None values recursively from all of the dictionaries, tuples, lists, sets"""
if isinstance(_dict, dict):
for key, value in list(_dict.items()):
if isinstance(value, (list, dict, tuple, set)):
_dict[key] = delete_none(value)
elif value is None or key is None:
del _dict[key]
elif isinstance(_dict, (list, set, tuple)):
_dict = type(_dict)(delete_none(item) for item in _dict if item is not None)
return _dict
passed:
a =
"a": 12, "b": 34, "c": None,
"k": "d": 34, "t": None, "m": ["k": 23, "t": None,[None, 1, 2, 3],1, 2, None], None: 123
returned:
a =
"a": 12, "b": 34,
"k": "d": 34, "m": ["k": 23, [1, 2, 3], 1, 2]
【讨论】:
您需要在_dict.items()
之前添加list()
以避免由于dict 在迭代期间更改大小而引发RunTimeError
value 可以是具有 None 属性的字典列表,添加elif isinstance(value, list): for v_i in value: delete_none(v_i)
不需要返回_dict。这只会增加运行时间。 _dict 通过引用方法传递。您可以将要从中删除的字典的副本传递给此函数并获取结果。
如果您在顶层有一个数组,则缺少一个案例: mylist: [ 1, 2,3 ]
@Mandragor 好点,谢谢,一开始就不能检查,比如: if not isinstance(_dict, dict): return _dict but your looks good【参考方案3】:
对于python 2.x
:
dict((k, v) for k, v in original.items() if v is not None)
【讨论】:
我不能代表反对者,但这里的答案有一个问题是,如果bool(v)
评估为 False
,not v
将评估为 True
。例如,v == ''
(空字符串)就是这种情况,这与 v == None
不同。
@Rob is not
不等于 is
和 not
的组合。它是一个完全独立的运算符来测试身份。请参阅 operator.is_not
for Python2 和 Python3。
@AminShahGilani 是的,答案已被编辑。它以前使用if not v
而不是if v is not None
。我现在应该删除我的评论吗?【参考方案4】:
您还可以复制dict
以避免在更改原始dict
时对其进行迭代。
for k, v in dict(d).items():
if v is None:
del d[k]
但这对于较大的字典可能不是一个好主意。
【讨论】:
【参考方案5】:如果你不想复制
for k,v in list(foo.items()):
if v is None:
del foo[k]
【讨论】:
foo.pop(k)
更好,否则会失败
仅供参考,list
关键字创建键/值对的(浅)副本。
foo.pop(k) 如果没有键也会失败,更好,pop(k, None)【参考方案6】:
Python3递归版本
def drop_nones_inplace(d: dict) -> dict:
"""Recursively drop Nones in dict d in-place and return original dict"""
dd = drop_nones(d)
d.clear()
d.update(dd)
return d
def drop_nones(d: dict) -> dict:
"""Recursively drop Nones in dict d and return a new dict"""
dd =
for k, v in d.items():
if isinstance(v, dict):
dd[k] = drop_nones(v)
elif isinstance(v, (list, set, tuple)):
# note: Nones in lists are not dropped
# simply add "if vv is not None" at the end if required
dd[k] = type(v)(drop_nones(vv) if isinstance(vv, dict) else vv
for vv in v)
elif v is not None:
dd[k] = v
return dd
【讨论】:
【参考方案7】:也许你会发现它很有用:
def clear_dict(d):
if d is None:
return None
elif isinstance(d, list):
return list(filter(lambda x: x is not None, map(clear_dict, d)))
elif not isinstance(d, dict):
return d
else:
r = dict(
filter(lambda x: x[1] is not None,
map(lambda x: (x[0], clear_dict(x[1])),
d.items())))
if not bool(r):
return None
return r
它会:
clear_dict(
'a': 'b', 'c': 'd': ['e': None, 'f': 'g', 'h': None]
)
->
'a': 'b', 'c': 'd': ['f': 'g']
【讨论】:
以上是关于在 Python 中使用 None 值删除字典中键的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
Python:如何递归地从 NESTED 数据结构(列表和字典)中删除 None 值?
python字典中键值对的值为中文,打印成转义字符,怎么解决