我有一个字典,我想从中删除这样的项目:
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"]}
答案 0 :(得分:2)
正如Alex Hall's answer所指出的那样,问题是您正在尝试访问刚刚删除的密钥。
这里的第一个问题是你在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)
,但是当外部循环移至("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
并消除任何具有共同元素的内容都可能导致无法预测的结果。所以这可能不是一个完成你想要做的事情的好方法。
答案 1 :(得分:1)
您尝试在迭代同一个集合时删除。这从来都不是一个好主意。请考虑这种方法:
更新第一个想法有点儿错误。
或者@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)
答案 2 :(得分:0)
当你想调试某些东西时,打印东西。
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]
,但它不能,因为它刚被删除。