就地 Python 字典逆

In-place Python dictionary inverse

我想看看是否可以解决的任务是,交换字典的键值对(在 Python 中),使用就地计算,无需额外数据-structures(只有固定数量的额外变量)。这似乎是不可能的(在有限的世界中),但我愿意听取有关解决它的建议。

我在 python 中看过几篇关于就地字典求逆的帖子,我发现所有解决方案之间有一个共同点。 以下字典将无法正确反转:

dict = {'b':'a','a':'c','c':123}

原因是,当交换第一个参数时,我们覆盖了'a'的实际值(值是唯一的,键是唯一的,但这并不意味着没有与现有密钥相同的值)

注释:

1) 作为示例给出的字典具有可哈希值。

2) key/values 可以是任何数据类型。不一定是字符串。

我很想听听解决它的方法,我想到了一个,但它只有在我们拥有无限内存的情况下才有效,这显然不是真的。

编辑:

1) 我的想法是,更改字典,以便在每个键条目的开头添加固定数量的下划线 ("_")。下划线的个数是根据key决定的,如果某个key有X个下划线,我就加X+1个下划线(max_underscores_of_key_in_prefix+1)。 为了解决键中的对象,我将为此制作一个包装器 class。 我已尽力解释我的直觉,但我不确定这是否可行。

2) @Mark Ransom 的解决方案非常有效,但如果有人有其他算法解决问题,我仍然很想听听! 我将这个问题标记为已解决,因为它已解决,但再次欢迎其他解决方案:-)

显然,要实现这一点,键和值都必须是可哈希的。这意味着 none 个键或值可以是 list。我们可以利用这一点来了解已经处理了哪些字典元素。

由于不能同时迭代和修改字典,我们必须在每次交换 key/value 时重新开始。这使得它非常慢,一个 O(n^2) 操作。

def invert_dict(d):
    done = False
    while not done:
        done = True
        for key, val in d.items():
            if isinstance(val, list):
                if len(val) > 1:
                    d[key] = [val[1]]
                    val = val[0]
            else:
                del d[key]
            if not isinstance(val, list):
                if val in d:
                    d[val] = [d[val], key]
                else:
                    d[val] = [key]
                done = False
                break
    for key, val in d.items():
        d[key] = val[0]