2012-04-04 57 views
1

可能重複:
Inverse dictionary lookup - Python指數Python字典按值

有一個內置的方式來索引一本詞典在Python值。

例如是這樣的:

dict = {'fruit':'apple','colour':'blue','meat':'beef'} 
print key where dict[key] == 'apple' 

或:

dict = {'fruit':['apple', 'banana'], 'colour':'blue'} 
print key where 'apple' in dict[key] 

或者我必須手動循環呢?

+2

請注意,'dict'中的'values'是唯一的,沒有限制,只有'keys'。當你的字典中有兩個相同的鍵時會發生什麼? – Hooked 2012-04-04 16:44:41

+2

@Hooked你的意思是「兩個相同的值」? – 2012-04-04 16:45:15

+0

@ root45是的我的意思是相同的「值」而不是「鍵」,對此感到遺憾。類似於:'A = {1:'foo',2:'foo'}'。 'foo'應該在這裏返回的是什麼? – Hooked 2012-04-04 16:46:40

回答

4

你必須手動循環,但如果你需要查找重複,這是一個方便的技巧:

d1 = {'fruit':'apple','colour':'blue','meat':'beef'} 

d1_rev = dict((v, k) for k, v in d1.items()) 

然後,您可以使用反向字典是這樣的:

>>> d1_rev['blue'] 
'colour' 
>>> d1_rev['beef'] 
'meat' 
+0

你應該至少提到最後一行的作用? – 2012-04-04 16:44:58

+0

meh。看起來很明顯 – bernie 2012-04-04 16:45:23

+2

@bernie:這對OP來說並不明顯,否則他不會問。一個簡單的「構建反向字典(value-> key)」就足夠了,但是沒有任何東西,這有點令人困惑 – 2012-04-04 16:45:49

5

你可以使用一個list comprehension

my_dict = {'fruit':'apple','colour':'blue','meat':'beef'} 
print [key for key, value in my_dict.items() if value == 'apple'] 

上面的代碼是做幾乎完全WH在說你想要的:

打印鍵,其中的dict [關鍵] ==「蘋果」

列表內涵是要在所有的鍵,值對你的字典的items method給出,並作出所有鍵值爲'apple'的新列表。

正如Niklas指出的,當您的值可能成爲列表時,這不起作用。在這種情況下,您必須小心使用in,因爲'apple' in 'pineapple' == True。因此,堅持列表理解方法需要進行一些類型檢查。所以,你可以使用這樣一個輔助功能:

def equals_or_in(target, value): 
    """Returns True if the target string equals the value string or, 
    is in the value (if the value is not a string). 
    """ 
    if isinstance(target, str): 
     return target == value 
    else: 
     return target in value 

接着,下面的列表解析會的工作:

my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'} 
print [key for key, value in my_dict.items() if equals_or_in('apple', value)] 
+0

我相信OP想要搜索值而不是密鑰。 – Amjith 2012-04-04 16:53:40

+0

@Amjith是的,我有一個大腦放屁。它已被修復。 – Wilduck 2012-04-04 16:54:22

+0

在更一般的第二個示例中不起作用 – 2012-04-04 16:56:39

3

你的要求是比你想象複雜得多:

  • 您需要處理列表值和明文值
  • 您實際上不需要取回密鑰,而是使用密鑰列表

你可以分兩步解決這個問題:

  1. 標準化字典,使每個值是一個列表(每平值成爲一個單一的元素)
  2. 建立反向字典

下列功能解決這個問題:

from collections import defaultdict 

def normalize(d): 
    return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() } 

def build_reverse_dict(d): 
    res = defaultdict(list) 
    for k,values in normalize(d).items(): 
     for x in values: 
      res[x].append(k) 
    return dict(res) 

要這樣來使用:

>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'}) 
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']} 
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'}) 
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']} 
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']}) 
{'duplicate': ['a', 'b']} 

所以,你剛剛建立的反向字典一次,然後由值查找並取回鍵的列表。

+0

我認爲'res [x]'有一個錯字,因爲你從未定義過'x'。 – Hooked 2012-04-04 17:11:46

+0

@Hooked:謝謝,的確,我編輯過的文章是爲了縮短文章的篇幅, – 2012-04-04 17:15:42