2016-03-17 42 views
1

因此,我必須編寫一個函數,它接收一個字典作爲輸入參數,並返回輸入字典的反向,其中原始字典的值用作返回字典的鍵,原始字典的鍵是用作返回字典的值。反向字典。輸出保持變化

例如,如果該功能被稱爲

reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']}) 

然後我的函數返回

{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']} 

這裏是我的功能

def reverse_dictionary(input_dict): 
    d={} 
    def countEmpty(dictionario): 
     count=0 
     for k,v in dictionario.items(): 
      if(len(dictionario[k])==0): 
       count+=1 
     return count 
    def removo(dicto, dicto2): 
     for k,v in dicto.items(): 
      #v.sort() 
      if (len(dicto[k])!=0): 
       if v[-1] not in dicto2: 
        dicto2[v[-1].lower()]=[k.lower()] 
       else: 
        dicto2[v[-1]].append(k.lower()) 
       dicto[k]=v[:-1] 
    while countEmpty(input_dict)<len(input_dict): 
     removo(input_dict,d) 
    for k,v in d.items(): 
     v.sort() 
    return d 

dicta={'astute': ['Smart', 'clever', 'talented'], 'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'talented': ['smart', 'keen', 'Bright'], 'smart': ['clever', 'bright', 'talented']} 
print(reverse_dictionary(dicta)) 

程序開始工作。它反轉字典。但字典中的值需要排序。 我測試過該程序具有:

dicta={'astute': ['Smart', 'clever', 'talented'], 'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'talented': ['smart', 'keen', 'Bright'], 'smart': ['clever', 'bright', 'talented']} 

它有時會返回:

{'keen': ['talented'], 'talented': ['astute', 'smart'], 'clever': ['astute', 'smart'], 'exact': ['accurate'], 'bright': ['smart', 'talented'], 'precise': ['accurate', 'exact'], 'smart': ['astute', 'talented']} 

哪個是正確答案,但有時它也返回:

{'bright': ['smart', 'talented'], 'exact': ['accurate'], 'talented': ['astute', 'smart'], 'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'smart': ['astute'], 'keen': ['talented']} 

其中有'聰明'鍵缺少'天賦'的價值。即使我沒有做任何改變代碼。我知道Python中的字典並沒有任何順序,但不應該保持一致?爲什麼會發生?

+1

詞典是由設計無序的。另外,決定用「精確」來做什麼決不是不可能的:['準確','確切']? 「準確」還是「準確」成爲關鍵? – jDo

+1

你正在修改你的字典,而迭代它...不是一個明智的想法 – Idos

+0

@jDo他們都將成爲鍵精確作爲他們兩個的價值 – slau

回答

0

可以使元組的原字典鍵每個值相關聯的排序列表,然後使用itertools.groupby,快譯通理解和列表comprehesion合併輸出:

import itertools 

d = {'accurate': ['exact', 'precise'], 
    'exact': ['precise'], 
    'astute': ['smart', 'clever'], 
    'smart': ['clever', 'bright', 'talented']} 

l = sorted([(v2,k) for k, v in d.items() for v2 in v]) 

{k:list(x[1] for x in g) for k, g in itertools.groupby(l, lambda x: x[0])} 

中級列表L:

[('bright', 'smart'), 
('clever', 'astute'), 
('clever', 'smart'), 
('exact', 'accurate'), 
('precise', 'accurate'), 
('precise', 'exact'), 
('smart', 'astute'), 
('talented', 'smart')] 

輸出:

{'bright': ['smart'], 
'clever': ['astute', 'smart'], 
'exact': ['accurate'], 
'precise': ['accurate', 'exact'], 
'smart': ['astute'], 
'talented': ['smart']} 
0

我已經能夠代表導致你的輸出不一致的錯誤。你的算法中可能有兩個問題。

  1. 您認爲密鑰將按順序迭代。
  2. 你正在迭代一個對象而改變它。這在Python 3.X中特別奇怪,其中items返回項目的視圖而不是顯式迭代(請參閱this question)。

看來,您可以通過以下行「解決」了這兩個問題:

for k,v in sorted(dicto.items()): 

這在我的測試提供了一個一致的,正確的輸出。我對不是很有信心,爲什麼這個工作,而缺乏解釋可能是爲什麼你不應該迭代改變的對象開始。


爲了好玩,這裏是一個不同的,愚蠢的解決方案:

import networkx as nx 

d = { 
    'Accurate': ['exact', 'precise'], 
    'exact': ['precise'], 
    'astute': ['Smart', 'clever'], 
    'smart': ['clever', 'bright', 'talented'] 
} 

# make keys uppercase and values lowercase 
d = {k.upper(): list(map(str.lower, v)) for k,v in d.items()} 

# fill out all of the edges 
expanded = nx.convert.to_dict_of_lists(nx.Graph(d)) 

# convert the uppercase values to lowercase and filter out the uppercase keys 
filtered = {k: list(map(str.lower, v)) for k,v in expanded.items() if k.islower()} 
0

你得到無序輸出因爲字典是由設計不排序。按照可預見的順序查看密鑰的唯一方法是使用collections.OrderedDict(字典替換),它只是按照它們插入的順序顯示它們。你不斷得到不同輸出每一次,因爲python的設計者,作爲一種抵禦拒絕服務攻擊的安全措施,引入了非確定性組件到密鑰存儲和返回的順序。

如果值在你的字典列表已經排序,你可以簡單的按鍵爲您檢索它們進行排序:

revdict = reverse_dictionary(dicta) 
for k in sorted(revdict): 
    print(k, revdict[k]) 

或等價(因爲元組由第一要素第一排序):

revdict = reverse_dictionary(dicta) 
for k, v in sorted(revdict.items()): 
    print(k, v)