就地 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]
我想看看是否可以解决的任务是,交换字典的键值对(在 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]