【问题标题】:Python: An elegant way to delete empty lists from Python dictionaryPython:一种从 Python 字典中删除空列表的优雅方法
【发布时间】:2013-02-11 13:52:33
【问题描述】:

我有一本字典:

default = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}

我希望将空值消除为:

default = {'a': ['alpha'], 'b': ['beta','gamma']}

我写了一个函数(按照网上找到的例子)

def remove_empty_keys(d):
    for k in d.keys():
        try:
            if len(d[k]) < 1:
                del[k]
        except:
            pass
        return(d)

我有以下问题:

1- 我没有找到为什么它总是返回以下的错误 -

remove_empty_keys(default)
 {'a': ['alpha'], 'b': ['beta'], 'g': []}

2- 是否有内置函数可以在不创建原始字典副本的情况下从 Python 字典中消除/删除 Null/None/空值?

【问题讨论】:

  • 您的问题似乎将None 的想法与空列表混为一谈。这让人更难理解。
  • 也许更好的说法是“是否有从字典中消除虚假值的功能”
  • 您的try...except 子句似乎没有任何作用,只是对自己隐藏自己的错误。如果您真的想使用 try/except,那么您应该始终指定您期望的异常(在本例中为 KeyError)。这样,他们就不会无意中隐藏不相关的错误。但在这种情况下,除非并行线程中有代码正在修改d,否则您永远不会收到关键错误,因为k 必须在d 中,因为它是由@ 返回的987654330@.

标签: python list dictionary


【解决方案1】:

没有内置的(AFAIK),但您可以通过 dict 理解轻松完成:

new_dict = {k:v for k,v in original_dict.items() if v}

如果你被旧版本的 python 卡住了(2.7 之前没有 dict 理解),你可以使用 dict 构造函数:

new_dict = dict((k,v) for k,v in original_dict.items() if v)

请注意,这并不适用(根据您的第二个问题)。并且字典不像列表那样支持切片分配,因此您真正能做到的最好的*是:

new_dict = {k:v for k,v in original_dict.items() if v}
original_dict.clear()
original_dict.update(new_dict)

*当然,“最佳”一词完全是主观的。

【讨论】:

    【解决方案2】:

    要修复您的功能,请将del[k] 更改为del d[k]。没有从字典中删除值的功能。

    您正在做的是删除变量k,根本不更改字典。这就是为什么总是返回原始字典的原因。

    重写,你的函数可能看起来像:

    def remove_empty_keys(d):
        for k in d.keys():
            if not d[k]:
                del d[k]
    

    这假设您要同时删除空列表和None 值,并实际删除任何具有“假”值的项目。

    【讨论】:

    • 在 Python 2 中,遍历 d.keys()(这是一个列表)可以删除循环中的值。在 Python 3 中,d.keys() 是 lazier。而是迭代list(d),或者构造一个新字典,如@mgilson's answer
    【解决方案3】:

    你可以使用dict理解:-

    >>> default = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}
    
    >>> {key: value for key, value in default.iteritems() if value}
    {'a': ['alpha'], 'b': ['beta', 'gamma']}
    

    【讨论】:

    • 问题不在于你在迭代它时修改字典——我实际上认为这可能没问题(尽管不要引用我的话)。这是 OP 正在做del [k] 而不是del d[k]。在我看来,第一种形式是创建一个列表然后删除它(尽管我可能错了,因为del 是一个声明......
    • @mgilson。是的,刚注意到。我将删除该行。
    【解决方案4】:
    dict((k, v) for k, v in default.iteritems() if v)
    

    这会过滤所有非空字符串、空字典/元组/列表的项目。

    【讨论】:

      【解决方案5】:

      还有一个选项如下(不创建新字典):

      for e in [k for k,v in default.iteritems() if len(v) == 0]: default.pop(e)
      

      【讨论】:

        【解决方案6】:

        Michael's answer 是正确的。

        退后一步,您也许可以完全避免创建那些空列表,通过使用collections.defaultdict(list)

        >>> import collections
        >>> d = collections.defaultdict(list)
        >>> d
        defaultdict(<type 'list'>, {})
        >>> d["hobbits"].append("Frodo")
        >>> d["hobbits"].append("Sam")
        >>> d
        defaultdict(<type 'list'>, {'hobbits': ['Frodo', 'Sam']})
        

        【讨论】:

          【解决方案7】:

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

          from itertools import compress
          d = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}
          new_d = dict(compress(d.items(), d.values()))
          print(new_d)  # {'a': ['alpha'], 'b': ['beta', 'gamma']}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-06
            • 2012-11-09
            • 2018-07-02
            • 2021-09-22
            相关资源
            最近更新 更多