从dict中删除带有空字符串的键的有效方法

ens*_*are 103 python dictionary

我有一个字典,并希望删除所有有空值字符串的键.

metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)',
            u'EXIF:CFAPattern2': u''}
Run Code Online (Sandbox Code Playgroud)

做这个的最好方式是什么?

Bre*_*arn 172

Python 2.X

dict((k, v) for k, v in metadata.iteritems() if v)
Run Code Online (Sandbox Code Playgroud)

Python 2.7 - 3.X

{k: v for k, v in metadata.items() if v is not None}
Run Code Online (Sandbox Code Playgroud)

请注意,您的所有键都有值.只是其中一些值是空字符串.在没有价值的字典中没有关键词; 如果它没有价值,它就不会出现在字典中.

  • +1.重要的是要注意,这实际上并没有从现有字典中删除密钥.相反,它创建了一个新的字典.通常这正是人们想要的,可能是OP所需要的,但它不是OP所要求的. (26认同)
  • 这也会杀死v = 0,这很好,如果这是想要的. (17认同)
  • 对于python的更高版本,你还应该使用字典生成器:`{k:v for k,v in metadata.items()如果v不是None} (6认同)
  • @shredding:你的意思是`.items()`. (4认同)
  • 这也消除了 v=False,这不是 OP 要求的 _exactly_。 (3认同)
  • 我认为对于 python3 最好的是:`{k: v for k, v in metadata.items() if v}` (2认同)

小智 71

它可以比BrenBarn的解决方案更短(我认为更具可读性)

{k: v for k, v in metadata.items() if v}
Run Code Online (Sandbox Code Playgroud)

用Python 2.7.3测试.

  • 这也会导致零值. (13认同)
  • 应始终将"无"与"不是"进行比较,而不是"!=".http://stackoverflow.com/a/14247419/2368836 (12认同)
  • 为了保留0(零)你可以使用`... if v!= None`如下:`{k:v for k,v in metadata.items()if v!= None}` (10认同)

nne*_*neo 20

如果你真的需要修改原始字典:

empty_keys = [k for k,v in metadata.iteritems() if not v]
for k in empty_keys:
    del metadata[k]
Run Code Online (Sandbox Code Playgroud)

请注意,我们必须列出空键,因为我们无法在迭代时修改字典(您可能已经注意到了).这比创建一个全新的字典更便宜(内存方面),除非有很多条目具有空值.

  • 如果您使用的是Python 3+,则必须将`.iteritems()`替换为`.items()`,第一个在最新的Python版本中不再起作用。 (2认同)

Mah*_*emi 12

如果你想要一个功能齐全但简洁的方法来处理经常嵌套的实际数据结构,甚至可以包含循环,我建议从boltons实用程序包中查看重映射实用程序.

之后pip install boltons或复制iterutils.py到您的项目,只是做:

from boltons.iterutils import remap

drop_falsey = lambda path, key, value: bool(value)
clean = remap(metadata, visit=drop_falsey)
Run Code Online (Sandbox Code Playgroud)

这个页面有更多的例子,包括使用Github API的更大对象的例子.

它是纯Python,因此它可以在任何地方使用,并且在Python 2.7和3.3+中进行了全面测试.最重要的是,我为这样的情况编写了它,所以如果你找到一个它无法处理的情况,你可以告诉我在这里解决它.


Joe*_*ett 9

BrenBarn的解决方案是理想的(和pythonic,我可能会添加).这是另一个(fp)解决方案,但是:

from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
Run Code Online (Sandbox Code Playgroud)


cha*_*han 9

根据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
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)


Hec*_*ros 7

对于蟒蛇 3

dict((k, v) for k, v in metadata.items() if v)
Run Code Online (Sandbox Code Playgroud)


Rya*_*yan 6

如果你有一个嵌套字典,并且你希望它甚至可以用于空子元素,你可以使用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
Run Code Online (Sandbox Code Playgroud)


dre*_*mac 5

快速解答(TL; DR)

范例01

### 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'}
'''
Run Code Online (Sandbox Code Playgroud)

详细答案

问题

  • 内容: Python 2.x
  • 场景:开发人员希望修改字典以排除空白值
    • aka从字典中删除空值
    • aka删除具有空白值的键
    • aka过滤器字典,用于每个键值对上的非空白值

  • example01使用带有简单条件的python list-comprehension语法删除“空”值

陷阱

  • example01仅对原始词典的副本进行操作(未就地修改)
  • example01可能会产生意外结果,具体取决于开发人员“空”的含义
    • 开发人员是否打算保留虚假的价值
    • 如果字典中的值不保证是字符串,则开发人员可能会意外丢失数据。
    • result01显示原始集合中仅保留了三个键值对

替代示例

  • example02帮助解决潜在的陷阱
  • 该方法是通过更改条件使用“空”的更精确定义。
  • 在这里,我们只想滤除评估为空字符串的值。
  • 在这里,我们还使用.strip()过滤出仅包含空格的值。

示例02

### 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'
  }
'''
Run Code Online (Sandbox Code Playgroud)

也可以看看


Mat*_*all 5

基于patriciasznneonneo的答案,并考虑到您可能想要删除仅包含某些虚假内容(例如'')但不包含其他内容(例如0)的密钥的可能性,或者您甚至可能想包含一些真实的内容(例如'SPAM') ,那么你可以制作一个非常具体的命中列表:

unwanted = ['', u'', None, False, [], 'SPAM']
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不太有效,因为例如0 in unwanted评估为True. 我们需要区分0其他虚假的东西,所以我们必须使用is

any([0 is i for i in unwanted])
Run Code Online (Sandbox Code Playgroud)

...评估为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]
Run Code Online (Sandbox Code Playgroud)

如果你想要一个新的字典,而不是metadata就地修改:

newdict = {k: v for k, v in metadata.items() if not any([v is i for i in unwanted])}
Run Code Online (Sandbox Code Playgroud)