Python 迭代字典并删除项目
Python iterating dictionary and delete item
我有一本字典,我想从中删除这样的项目:
for key1 in d.keys():
for key2 in d.keys():
if len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
但是我收到一个错误:KeyError。我正在使用 Python 2.7,如果有人知道如何做到这一点,我正在等待您的回答。
我的字典看起来像:
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5"]}
当你想调试某些东西时,打印一些东西。
for key1 in d.keys():
print 'key1', key1
print 'inner d.keys', d.keys()
for key2 in d.keys():
print 'key2', key2
if len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
print 'deleted, new d.keys', d.keys()
key1 ('a', '1')
inner d.keys [('a', '1'), ('b', '2')]
key2 ('a', '1')
deleted, new d.keys [('b', '2')]
key2 ('b', '2')
Traceback (most recent call last):
File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 8, in <module>
if len(set(d[key1]) & set(d[key2])) > 0:
KeyError: ('a', '1')
也就是说,它要求 d[key1]
但它不能,因为它刚刚被删除。
您在迭代同一集合时尝试删除。这绝不是一个好主意。请考虑以下方法:
更新第一个想法有点错误。
或按照@Alex Hall 在评论中的建议进行一些简化:
from itertools import combinations
keys_pairs = combinations(d.keys(), 2)
keys_to_delete = set()
for key1, key2 in keys_pairs:
if len(set(d[key1]) & set(d[key2])) > 0:
keys_to_delete.add(key2)
for key in keys_to_delete:
d.pop(key)
正如 指出的那样,问题是您正在尝试访问刚刚删除的密钥。
这里的第一个问题是您没有跳过 key1 == key2
时的大小写。发生这种情况时,交集将总是 有元素。你想避免这种情况。所以:
for key1 in d.keys():
for key2 in d.keys():
if key1 != key2 and len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
这修复了您的循环,以解决它们不是公共元素的情况。但是还有更多的问题。考虑这个 dict
,例如:
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5", "c1"]}
这试图删除 ("b", 2)
,但是当 outer 循环移动到 ("b", "2")
时,它已经被删除了。所以你需要跳过那个案例:
for key1 in d.keys():
if key1 in d:
for key2 in d.keys():
if key1 != key2 and len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
这给了我们想要的,删除了后一个元素:
{('a', '1'): ['c1', 'c2', 'c3']}
但是...仍然有很多奇怪的案例需要考虑。这个怎么样?
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5", "c1"], ("c", "3") : ["c4", "c5"]}
这取决于你删除东西的顺序,你不能依赖dict
中的任何键顺序。那么问题来了,你究竟想要完成什么?将所有内容都推入 dict
并删除任何具有共同元素的内容可能会导致不可预知的结果。所以这可能不是完成你想做的事情的好方法。
我有一本字典,我想从中删除这样的项目:
for key1 in d.keys():
for key2 in d.keys():
if len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
但是我收到一个错误:KeyError。我正在使用 Python 2.7,如果有人知道如何做到这一点,我正在等待您的回答。 我的字典看起来像:
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5"]}
当你想调试某些东西时,打印一些东西。
for key1 in d.keys():
print 'key1', key1
print 'inner d.keys', d.keys()
for key2 in d.keys():
print 'key2', key2
if len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
print 'deleted, new d.keys', d.keys()
key1 ('a', '1')
inner d.keys [('a', '1'), ('b', '2')]
key2 ('a', '1')
deleted, new d.keys [('b', '2')]
key2 ('b', '2')
Traceback (most recent call last):
File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 8, in <module>
if len(set(d[key1]) & set(d[key2])) > 0:
KeyError: ('a', '1')
也就是说,它要求 d[key1]
但它不能,因为它刚刚被删除。
您在迭代同一集合时尝试删除。这绝不是一个好主意。请考虑以下方法:
更新第一个想法有点错误。
或按照@Alex Hall 在评论中的建议进行一些简化:
from itertools import combinations
keys_pairs = combinations(d.keys(), 2)
keys_to_delete = set()
for key1, key2 in keys_pairs:
if len(set(d[key1]) & set(d[key2])) > 0:
keys_to_delete.add(key2)
for key in keys_to_delete:
d.pop(key)
正如
这里的第一个问题是您没有跳过 key1 == key2
时的大小写。发生这种情况时,交集将总是 有元素。你想避免这种情况。所以:
for key1 in d.keys():
for key2 in d.keys():
if key1 != key2 and len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
这修复了您的循环,以解决它们不是公共元素的情况。但是还有更多的问题。考虑这个 dict
,例如:
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5", "c1"]}
这试图删除 ("b", 2)
,但是当 outer 循环移动到 ("b", "2")
时,它已经被删除了。所以你需要跳过那个案例:
for key1 in d.keys():
if key1 in d:
for key2 in d.keys():
if key1 != key2 and len(set(d[key1]) & set(d[key2])) > 0:
del d[key2]
这给了我们想要的,删除了后一个元素:
{('a', '1'): ['c1', 'c2', 'c3']}
但是...仍然有很多奇怪的案例需要考虑。这个怎么样?
{("a", "1") : ["c1", "c2", "c3"], ("b", "2") : ["c4", "c5", "c1"], ("c", "3") : ["c4", "c5"]}
这取决于你删除东西的顺序,你不能依赖dict
中的任何键顺序。那么问题来了,你究竟想要完成什么?将所有内容都推入 dict
并删除任何具有共同元素的内容可能会导致不可预知的结果。所以这可能不是完成你想做的事情的好方法。