2012-04-05 45 views
1

我想將鍵更改爲python字典中的值,但原始字典中的值不唯一。當值不是唯一的時,在python字典中轉置值和鍵

以下是我有:

year_person = {2000: ‘Linda’, 2001: ‘Ron’, 2002: ‘Bruce’, 2003: ‘Linda’, 2004: ‘Bruce’, 2005 ‘Gary’, 2006: ‘Linda’} 

這是我想將它更改爲:

person_year = {‘Linda’: 2000, ‘Ron’: 2001, ‘Bruce’: 2002, ‘Linda’, 2003: ‘Bruce’, 2004 ‘Gary’, 2005: ‘Linda’: 2006} 

當我試圖用它來轉換一個for循環,我只得到了一個匹配爲每個人配對。

+3

你不能那樣做。每個密鑰必須是唯一的。您可以創建每個鍵的所有值的列表。 – alan 2012-04-05 22:16:14

+2

rel:http://stackoverflow.com/q/483666/989121 – georg 2012-04-05 22:16:44

回答

2

你想達到的目標在技術上是不可行的。字典的關鍵字不能重複,因爲如果是這樣的話,你不能唯一索引一個帶有關鍵字的字典。

你可以做的是創建一個(鍵,值)對的字典,其中value是具有相同鍵的所有項目的列表。爲了實現它,你可以做一些事情如下

>>> person_year={} 
>>> [person_year.setdefault(v,[]).append(k) for (k,v) in year_person.iteritems()] 
[None, None, None, None, None, None, None] 
>>> person_year 
{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 
>>> 

注意,如果你只在鍵值對感興趣,而不是一本字典本身」你可以存儲爲元組的列表如下

>>> [(v,k) for k,v in year_person.iteritems()] 
[('Linda', 2000), ('Ron', 2001), ('Bruce', 2002), ('Linda', 2003), ('Bruce', 2004), ('Gary', 2005), ('Linda', 2006)] 
>>> 
+1

我將其描述爲unpythonic - 列表理解旨在用於創建列表,而不是處理數據。在這種情況下,一個更清晰,更清晰的解決方案是alan給出的defaultdict。另外值得注意的是''iteritems()''只存在Python 3.0以前的版本,之後只需使用''items()''。 – 2012-04-05 22:49:55

8

你也可以用defaultdict做到這一點:

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'} 

from collections import defaultdict 
d = defaultdict(list) 
for k, v in year_person.items(): 
    d[v].append(k) 

print dict(d) 
>>> {'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 
+3

如果有人要使用'defaultdict',那麼當實現此功能的函數返回時,它應該轉換爲常規的'dict'。 'defaultdict'具有隱式地將錯過的屬性命中轉換爲插入的煩人特性。即當這不是你想要的時候它會產生錯誤。 – aaronasterling 2012-04-06 16:37:19

+0

是的,這就是爲什麼我將它轉換爲'print'語句。 – alan 2012-04-06 16:44:38

+3

這是說明潛在問題的不完全透明的方式。 – aaronasterling 2012-04-06 16:48:19

3

只是提出一些其他的選擇和信息可能會從目前的答案會丟失:

如果您確定您的值是唯一的,因此可以成爲關鍵,最簡單的方法是一個字典理解:

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'} 
person_year = {key: value for (value, key) in year_person.items()} 

當然,你的情況,他們都沒有,所以這是行不通(因爲它僅給出了最後的價值發現):

person_year = {'Bruce': 2004, 'Linda': 2006, 'Ron': 2001, 'Gary': 2005} 

相反,我們可以使用嵌套表補償的字典裏面補償:

{key: [value for value, check_key in year_person.items() if check_key==key] for key in year_person.values()} 

給我們:

{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 

這個工作,但效率不高,因爲必須遍歷每個條目的整個詞典。一個更好的解決方案是由alan給出的the defaultdict solution,它只需要一個循環。

2

IMO,defaultdict在這裏是不必要的,並且將其作爲列表理解來犧牲可讀性(儘管通常情況並非如此)。除非分析表明,這的確是一個瓶頸,我會如下做到這一點:

def invert_to_lists(dct): 
    inverted_dict = {} 
    for key in dct: 
     inverted_dict.setdefault(dct[key], []).append(key) 
    return inverted_dict 

defaultdict是一個更復雜。在這種情況下使用setdefault是很好的,因爲它只需要輸入一次。在完成導入和實例化defaultdict之後,您將輸入的內容多於撥打setdefault

+0

那麼問題是什麼?爲什麼downvote? – aaronasterling 2012-04-05 23:57:28

相關問題