2011-11-24 479 views

回答

0

我不知道最好的解決方案,但有一種可能性是顛倒字典(使值成爲鍵),然後只是做一個普通的密鑰查找。這將扭轉詞典:

forward_dict = { 'key1': 'val1', 'key2': 'val2'} 
reverse_dict = dict([(v,k) for k,v in forward_dict.items()]) 

因此給予 「VAL1」,我可以這樣做:

reverse_dict["val1"] 

找到對應的按鍵。此解決方案存在明顯的問題 - 例如,如果您的值不唯一,您將失去一些信息。

+0

如果字典包含不可取值,這不起作用,所以它不適用於問題中的示例。 –

+1

爲了展開彼得的解釋,字典不是不可變的,因此不可散列,所以字典不能成爲字典的關鍵。 「如果一個對象具有在其生命週期中從不改變的哈希值,則該對象是可散列的」 - Python術語表。 – Dave

0

編寫反轉字典的代碼(即創建一個將舊字典值映射到舊字典值的新字典)。
既然你似乎在處理嵌套字典,這顯然會更棘手。找出解決問題所需的最少數量和代碼(即,如果您的問題僅處理字典中沒有任何字典的字典,則不要創建任意嵌套深度的解決方案)

1

如果你不想扭轉字典,這裏的另一個可能的解決方案:

def get_key_from_value(my_dict, v): 
    for key,value in my_dict.items(): 
     if value == v: 
      return key 
    return None 

>>> d = {1: 'one', 2: 'two'} 
>>> get_key_from_value(d,'two') 
2 
+0

與Codemonk的迴應相同的問題 - 它不回答問題。 OP指定d是一個字典,其值是字典,而不是字符串。 – Dave

1

下面創建一個反向字典兩級例如:

d={'dict2': {1: 'one', 2: 'two'}, 'dict1': {3: 'three', 4: 'four'}} 
r = {} 
for d1 in d: 
    for d2 in d[d1]: 
     r[d[d1][d2]] = d1 

結果:

>>> r 
{'four': 'dict1', 'three': 'dict1', 'two': 'dict2', 'one': 'dict2'} 
2

這裏有一個遞歸解決方案,它能夠處理任意嵌套的字典:

>>> import collections 
>>> def dict_find_recursive(d, target): 
...  if not isinstance(d, collections.Mapping): 
...   return d == target 
...  else: 
...   for k in d: 
...    if dict_find_recursive(d[k], target) != False: 
...     return k 
...  return False 

這不是從長遠來看,作爲一個有效率的「反向辭典」,但是如果你沒有做這樣的反向搜索頻繁,這可能沒有關係。 (請注意,您必須明確比較dict_find_recursive(d[k], target)False的結果,因爲否則諸如''之類的錯誤鍵會導致搜索失敗。事實上,即使此版本失敗,如果使用False作爲關鍵字;完全一般的解決方案將使用唯一的哨點object()指示虛假)

一些用法示例:

>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'}} 
>>> dict_find_recursive(d, 'two') 
'dict2' 
>>> dict_find_recursive(d, 'five') 
False 
>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'}, 
     'dict3': {1: {1:'five'}, 2: 'six'}} 
>>> dict_find_recursive(d, 'five') 
'dict3' 
>>> dict_find_recursive(d, 'six') 
'dict3' 

如果你想扭轉任意組嵌套的字典,遞歸發電機是你的朋友:

>>> def dict_flatten(d): 
...  if not isinstance(d, collections.Mapping): 
...   yield d 
...  else: 
...   for value in d: 
...    for item in dict_flatten(d[value]): 
...     yield item 
... 
>>> list(dict_flatten(d)) 
['three', 'four', 'five', 'six', 'one', 'two'] 

上面只是列出了字典中所有不是映射的值。然後,您可以像這樣每個這些值映射到一個關鍵:

>>> def reverse_nested_dict(d): 
...  for k in d: 
...   if not isinstance(d[k], collections.Mapping): 
...    yield (d[k], k) 
...   else: 
...    for item in dict_flatten(d[k]): 
...     yield (item, k) 
... 

這會產生一個元組的迭代,所以沒有信息丟失:

>>> for tup in reverse_nested_dict(d): 
...  print tup 
... 
('three', 'dict1') 
('four', 'dict1') 
('five', 'dict3') 
('six', 'dict3') 
('one', 'dict2') 
('two', 'dict2') 

如果你知道你的所有非映射值是可哈希 - 如果你知道它們是唯一的,或者如果你不關心碰撞 - 然後就通過所產生的元組dict()

>>> dict(reverse_nested_dict(d)) 
{'six': 'dict3', 'three': 'dict1', 'two': 'dict2', 'four': 'dict1', 
'five': 'dict3', 'one': 'dict2'} 
0

要處理的嵌套字典我會就像senderle's answer一樣。

但是,如果將來它不包含嵌套字典,請務必做一個簡單的逆轉。按設計字典是唯一的,但值沒有這個要求。

如果您的多個鍵的值相同,則在翻轉字典時,您將失去,但其中除了一個。而且由於字典沒有排序,你可能會隨意丟失不同的數據。逆轉工作的

例子:

>>> d={'dict1': 1, 'dict2': 2, 'dict3': 3, 'dict4': 4} 
>>> rd = dict([(v,k) for k,v in d.items()]) 
>>> print d 
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 2} 

>>> print rd 
{1: 'dict1', 2: 'dict2', 3: 'dict3', 4: 'dict4'} 

逆轉失敗的例子:注意dict4丟失

>>> d={'dict1': 1, 'dict2': 4, 'dict3': 3, 'dict4': 4} 
>>> rd = dict([(v,k) for k,v in d.items()]) 
>>> print d 
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 4} 

>>> print rd 
{1: 'dict1', 3: 'dict3', 4: 'dict2'} 
0

這裏是一個例子沒有人認爲有關:(可以同樣使用)

raw_dict = { 'key1': 'val1', 'key2': 'val2', 'key3': 'val1' } 

new_dict = {} 
for k,v in raw_dict.items(): 
    try: new_dict[v].append(k) 
    except: new_dict[v] = [k] 

結果:

>>> new_dict 
{'val2': ['key2'], 'val1': ['key3', 'key1']} 

也許不是最好的方法,但它的工作原理爲我需要它。