2015-07-13 57 views
5

我正在寻找交换给定字典的所有键值对的方法。在字典中交换键值对

到目前为止,我能想到的一种方式做它:

例:

>>>a = { 0: 'a', 1 : 'b', 2 : 'c' } 
>>> {value : key for key,value in a.items()} 
{'a': 0, 'b': 1, 'c' : 2} 

但为了这个,我将不得不使用额外的空间来声明另一个字典。
我想知道我可以使用哪些方法将键值对交换更多的空间效率。

+4

如果两个值重复或者您有一个不可哈希值? –

+0

@PadraicCunningham那么,如果两个(或更多)键具有相同的值,那么覆盖将是唯一的方法。我猜 ! –

+0

@PadraicCunningham我没有想过这个难以置信的价值场景!任何建议将有助于 –

回答

3

但为此,我将不得不使用额外的空间来声明另一个字典。

由于字典本质上是一个查找表,因此它有一种具体的方式将其放在内存中;密钥被有效地分配,并且指向它们本身没有特殊含义的值。因此,当你想要反转映射时,你不能真正使用现有的结构;相反,您将不得不从头开始创建新的字典条目。你在你的问题中使用的字典理解是一个很好和明确的方法来做到这一点。

什么你可能但是做的是重新使用字典你已经拥有并添加新键有(同时去除旧的):

for k in a: 
    a[a[k]] = k 
    del a[k] 

这会修改同一个字典,所以它赢得”不会有新词典的(可能很少)开销。请注意,这假定所有值都是唯一的,因此映射可以完全相反,并且键和值集不共享公共值。否则,您将遇到字典大小更改的异常或缺失的值。您可以通过创建字典密钥的副本避免前(虽然这意味着你有一个列表存储现在太):

for k in list(a): 
    if a[k] != k: 
     a[a[k]] = k 
     del a[k] 

最后请注意:这有可能是字典多次修改这样的威力虽然有一些重新映射的副作用(增加散列表大小等),但这是CPython的可能实现细节(我不太确定它)。

+1

正如所写的,这不会(1)给出字典改变大小的错误,并且(2)在某些情况下不起作用,例如, 'a = {1:1,2:3,3:2}'? – DSM

+0

@DSM是的,这可能是可能的,尽管它用OP的例子为我工作。您可能必须创建密钥列表的副本。至于(2),是的,对于这个例子它会中断,但我假设的情况类似于OP的例子,其中键集和值集是不同的。 – poke

0

试试看看这个代码。在反转键和值之前,它会删除字典中的项目。

for k, v in a.items(): 
    del a[k] 
    a[v] = k 
0

为避免覆盖@DSM在@ poke的答案中指出的特殊情况,我建议您始终使用第二个字典。性能是相同的。

b = dict() 
for k, v in a.items(): # a.iteritems() in python 2 
    b[v] = k 
    del a[k] 
a = b