删除值为空列表的字典的键

Delete keys of a dictionary whose values are empty lists

我有一本字典,其中一些与键对应的值是空列表。我想删除所有这样的键

d = {'Receipt total': [], 'Total Amount (AED)': [], 'Grand total': [], 'Net Amount': [], 'Total': ['105.00'], 'Total (AED)': [], 'Total Invoice Amount': [], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

预期输出:

d = {'Total': ['105.00'], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

我试过了:

for key, value in d.items():
    if value is None:
        del d[k]

我的代码不工作

怎么样:

new_d = dict((k,v) for k,v in d.items() if v)

如果您想覆盖 d,只需将 new_d 更改为 d

存在一些可能会给出错误结果的风险:

if vv = [] 将评估为 Falsly,与 0 相同,因此它可能会删除错误的密钥。在我的回答中,我没有解决这个问题。可以参考下面的link更好理解:

您可以使用:

d = {'Receipt total': [], 'Total Amount (AED)': [], 'Grand total': [], 'Net Amount': [], 'Total': ['105.00'], 'Total (AED)': [], 'Total Invoice Amount': [], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

res = {}

for key, value in d.items():
    if value:
        res[key] = value

res
# {'Total': ['105.00'], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

不建议在 for 循环期间从容器中删除项目,最好创建一个新的并添加你需要的,而不是从原来的中删除你不需要的。

例如:

a = [1,2,2,3]
for item in a:
    if item > 1:
        a.remove(item)
a
# [1, 2]

留下第二个 2 因为一旦你删除了第一个 2 你移动了索引并且你的 for 循环已经检查了索引 1 但现在你的第二个 2 是在索引 1 处,它未被选中。

您的字典 dDict[str, List[str]] 类型。它的初始化方式意味着 none 的键值是 None,而是空列表。例如:

>>> listOfNothing = []

>>> print(listOfNothing)
[]

>>> print(type(listOfNothing))
<class 'list'>

如果你想检查 list 是否为空(值是否为空列表),我建议这样:

for key, value in d.items():
    if len(value) == 0:
        [do something]

但是,正如其他人正确指出的那样,您无法在遍历字典时更改字典的大小。这可以是 solved by creating a new dictionary.

试试这个:

result = {k:v for k,v in d.items() if v}

您可以使用 dictionary comprehension 代替:

d = {'Receipt total': [], 'Total Amount (AED)': [], 'Grand total': [], 'Net Amount': [], 'Total': ['105.00'], 'Total (AED)': [], 'Total Invoice Amount': [], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}
    
d = {k: v for k, v in d.items() if v != []}

print(d)

# d = {'Total': ['105.00'], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

您可能想要明确检查该值是否为 []。否则,您可以删除碰巧评估为 False(“falsey”)的东西,例如0 个您可能不想要的值。当然,只有当您的字典可以包含列表以外的值作为值时,这一点才有意义。

你可以像这样使用字典理解:

d = {'Receipt total': [], 'Total Amount (AED)': [], 'Grand total': [], 'Net Amount': [], 'Total': ['105.00'], 'Total (AED)': [], 'Total Invoice Amount': [], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

#use dictionary comprehensiion to create a new list of values where they value is not an empty list
d = {key : value for key, value in d.items() if len(value) != 0}

print(d)

输出:{'Total': ['105.00'], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

通过使用 for 循环删除字典中的项目,会引发 RuntimeError: dictionary changed size during iteration

如果值都是列表,那么你可以使用它们的真实性,你可以使用 itertools.compress

>>> dict(compress(d.items(), d.values()))
{'Total': ['105.00'], 'Invoice total': ['105.00'], 'Amount Due': ['0.00']}

你的思路至少有3处错误。

首先是一个空列表和None一样。

只有NoneNone相同。

其次,比较列表,你应该使用==。使用 is 来比较一个列表意味着,即使一个列表中有相同的值,如果它不是实际相同的内存地址,它也不会比较相等。

此外,由于您只想知道列表是否为空,因此您可以使用以下事实:在 Python 中,空序列被视为 False,非空序列被视为 True,因此您可以使用布尔条件:if not value: 对于空列表将是 True。如果值可以是列表以外的其他内容,那么空字符串、零等也都是 False,因此您可能需要更仔细地检查。

第三,您不应该在迭代时像 dict 那样修改容器的大小。 要么遍历它的一个副本,要么创建一个你想要修改的东西的记录,然后再执行修改。

第一种方式,遍历一个副本:

for key, value in list(d.items()):
    if not value:
        del d[key]

第二种方式,制作一组要删除的键:

keys_to_remove = {key for key, value in d.items()
                  if not value}

for key in keys_to_remove:
    del d[key]