【问题标题】:Delete keys of a dictionary whose values are empty lists删除值为空列表的字典的键
【发布时间】:2021-01-20 11:39:46
【问题描述】:

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

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]

我的代码不工作

【问题讨论】:

  • 错误信息/回溯是什么?
  • 应该是key而不是k
  • 你怎么知道它不起作用?了解如何创建minimal reproducible example
  • [] is not None
  • @Steve 他们的代码还没有达到那个错误。

标签: python python-3.x dictionary key-value


【解决方案1】:

您可以改用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 您可能不想要的值。当然,只有当您的 dict 可以包含列表以外的内容作为值时,这一点才有意义。

【讨论】:

    【解决方案2】:

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

    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

    【讨论】:

      【解决方案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]
      

      【讨论】:

      • 在迭代时更改 dict 的 values 是否有问题?你的说法对我来说太笼统了。
      • @KellyBundy 抱歉,当我说“不应该修改容器”时,我指的是容器的结构,即值的数量。当然,如果容器中的值是可变的,那么您可以修改它们。更新。谢谢。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        你可以使用:

        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上并且它没有被选中。

        【讨论】:

          【解决方案6】:

          试试这个:

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

          【讨论】:

            【解决方案7】:

            怎么样:

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

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

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

            if vv = [] 将评估为 Falsly 时,与 0 相同,因此它可能会删除错误的密钥。在我的回答中,我没有解决这个问题。可以参考以下链接更好理解:What is Truthy and Falsy? How is it different from True and False?

            【讨论】:

            • 原字典需要修改怎么办?
            • @PeterWood 你的意思是在迭代它的时候?我只建议了一个返回所需输出的解决方案。
            • 问题说他们想删除键。
            • @PeterWood 我没有看到明显的区别,这将“删除”不需要的键并返回所需的解决方案。大多数解决方案都与我建议的相同。
            • 也许最好注意你的答案中存在错误的风险。
            【解决方案8】:

            您拥有的字典dDict[str, List[str]] 类型。它的初始化方式意味着所有键的值都不是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

            【讨论】:

            • 一个空列表是False-y: if not value:
            • 在迭代字典时修改它的键是否安全?
            • @PeterWood 你说得对,编辑了我的答案以包含一个有用的 StackOverflow 问题的链接,因为这个问题实际上是一个二合一的问题。
            猜你喜欢
            • 2021-12-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-11-06
            • 1970-01-01
            • 2020-03-24
            • 1970-01-01
            相关资源
            最近更新 更多