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 并删除任何具有共同元素的内容可能会导致不可预知的结果。所以这可能不是完成你想做的事情的好方法。