关于python:当值未知时从字典中删除项目

Remove an item from a dictionary when its key is unknown

按值从字典中删除项的最佳方法是什么,即当项的键未知时?下面是一个简单的方法:

1
2
3
for key, item in some_dict.items():
    if item is item_to_remove:
        del some_dict[key]

有更好的方法吗?在迭代字典时,从字典中改变(删除项目)有什么问题吗?


dict.pop(key[, default])方法允许您在知道密钥时删除项目。如果移除项,则返回键处的值,否则返回作为default传递的值。看医生。

例子:

1
2
3
4
5
6
7
8
9
>>> dic = {'a':1, 'b':2}
>>> dic
{'a': 1, 'b': 2}
>>> dic.pop('c', 0)
0
>>> dic.pop('a', 0)
1
>>> dic
{'b': 2}


请注意,您当前正在测试对象标识(is只返回True,如果两个操作数在内存中都由同一个对象表示—这并不总是两个对象的情况与==相比较。如果您是故意这样做的,那么您可以将代码重写为

1
2
some_dict = {key: value for key, value in some_dict.items()
             if value is not value_to_remove}

但这可能不符合您的要求:

1
2
3
4
5
6
7
8
>>> some_dict = {1:"Hello", 2:"Goodbye", 3:"You say yes", 4:"I say no"}
>>> value_to_remove ="You say yes"
>>> some_dict = {key: value for key, value in some_dict.items() if value is not value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 3: 'You say yes', 4: 'I say no'}
>>> some_dict = {key: value for key, value in some_dict.items() if value != value_to_remove}
>>> some_dict
{1: 'Hello', 2: 'Goodbye', 4: 'I say no'}

所以你可能要用!=而不是is not


1
2
a = {'name': 'your_name','class': 4}
if 'name' in a: del a['name']


del和pop()之间的简单比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
import timeit
code ="""
results = {'A': 1, 'B': 2, 'C': 3}
del results['A']
del results['B']
"""

print timeit.timeit(code, number=100000)
code ="""
results = {'A': 1, 'B': 2, 'C': 3}
results.pop('A')
results.pop('B')
"""

print timeit.timeit(code, number=100000)

结果:

1
2
0.0329667857143
0.0451040902256

所以del比pop()更快。


我会建立一个需要删除的键列表,然后删除它们。它简单、高效,避免了同时迭代和修改dict的任何问题。

1
2
3
4
keys_to_remove = [key for key, value in some_dict.iteritems()
                  if value == value_to_remove]
for key in keys_to_remove:
    del some_dict[key]


items()返回一个列表,这就是您正在迭代的列表,因此在循环中改变dict在这里并不重要。如果您使用iteritems(),那么在循环中改变dict将是有问题的,在python 2.7中,对viewitems()也是如此。

我想不出一个更好的方法来按值从dict中删除项目。


C是新字典,A是你原来的字典,'Z'、'W'是要从中删除的密钥

1
c = {key:a[key] for key in a.keys() - {'z', 'w'}}

另请查看:https://www.safaribooksonline.com/library/view/python-cookbook-3rd/9781449357337/ch01.html


1
2
y={'username':'admin','machine':['a','b','c']}
if 'c' in y['machine'] : del y['machine'][y['machine'].index('c')]

我就是这样做的。

1
2
3
4
for key in some_dict.keys():
    if some_dict[key] == item_to_remove:
        some_dict.pop(key)
        break

正如您所建议的,在迭代时从字典中删除项目没有任何错误。注意多个线程同时使用同一个字典,这可能导致键错误或其他问题。

当然,请参见http://docs.python.org/library/stdtypes.html typesmapping上的文档。