2017-07-08 27 views
2

如何將常用值的字典的鍵合併到元組中。例如:合併單個字典的常見值的密鑰的Python方式

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

output = {('E2', 'E5'): {'5', '7'}, ('E3', 'E8'): {'4', '8'}} 

我嘗試:

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

output = {} 
seen = [] 
for k, v in A.items(): 
    if v not in [s[1] for s in seen]: # not seen this value yet 
     print('NOT SEEN') 
     print(k, v) 
     seen.append([k,v]) 
     output[k] = v 
    else: # already seen it 
     print('SEEN') 
     print(k, v) 
     # determine where we've seen it 
     where = [x for x in seen if x[1]==v] 
     output.pop(where[0][0]) 
     output[(where[0][0], k)] = v 


print('OUTPUT = ', output)  

此打印:

OUTPUT = {('E2', 'E5'): {'7', '5'}, ('E3', 'E8'): {'4', '8'}} 
+2

好吧,有什麼阻止你這樣做呢?你有具體的問題嗎? – vaultah

+1

@vaultah轉述爲問題 –

+1

我們說我們希望看到您的努力。 「給我代碼」這類問題一般都會被忽視。尤其是當一個或兩個迴路足以解決問題時。 –

回答

2

你可以試試這個:

from collections import defaultdict 

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

second_new = defaultdict(list) 

for a, b in A.items(): 
    second_new[tuple(b)].append(a) 

final_dict = {tuple(b):set(a) for a, b in second_new.items()} 

輸出:

{('E8', 'E3'): {'8', '4'}, ('E5', 'E2'): {'5', '7'}} 
+0

錯了......嘗試在發佈之前運行代碼... –

+1

@Pii請參閱我最近的編輯。 – Ajax1234

+0

謝謝。這是最簡單和容易理解的。 –

2
import itertools 

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

def key(x): 
    # List supports ordering 
    return sorted(list(x[1])) 

def gen(): 
    for (group_key, group) in itertools.groupby(sorted(A.items(), key=key), key=key): 
     gl = list(group) 
     yield (tuple(x[0] for x in gl), 
       gl[0][1] # group_key is a list, but we want original set 
      ) 

print(dict(gen())) 

如果你準備說服自己,SET->列表 - >設置轉換安全,那麼你可以做一個班輪,而不是發電機:

print(dict((tuple(g[0] for g in group), set(group_key)) for 
      (group_key, group) in 
      itertools.groupby(sorted(A.items(), key=key), key=key))) 

UPD:那麼,這裏究竟發生了什麼?

首先,我們通過調用.items()將字典轉換爲元組的迭代。 我們希望將具有相同第二個元素(具有索引1或前面的詞典值)的此迭代項目組合在一起。 這正是itertools.groupby所做的。論點是我們將要分組的一個迭代和關鍵。看起來,key=lambda kv: kv[1]是要走的路。不幸的是,我們可以比較集合的平等性,但文檔說可迭代應該是有序的。和sorted函數需要鍵可比較的順序。無法通過列表罐來比較集合。我們可以安全地創建一個包含與set相同的元素的列表,但我們應該對它進行排序(相同的集合可以生成不同順序的列表,{5, 7} == {7, 5},但是[5, 7] != [7, 5])。

現在,排序和分組,我們有以下數據結構之後:

[ 
    (key_dict_value as list, iterable of (dict_key, dict_value) that has dict_value == key_dict_value), 
    ... 
] 

現在,我們可以在這個迭代迭代和創建的元組的另一迭代。我們採用每個元組的第二個元素(可以迭代,索引爲1)並將其轉換爲元組(這是我們未來字典的關鍵)。我們未來字典的價值是來自原始字典的價值。我們可以從元組的第二個元素的某個元素(這個迭代不能爲空,因爲groupby不能產生空的組,見第一個片段)或者從key_dict_value轉換回列表(這是安全的,因爲這個列表是從集合中產生,因此它沒有相同的元素,請參閱第二個片段)。

UPD2

雖然我寫的說明,我要指出的是平等的關鍵不是罰款sorted但罰款groupby,所以這裏沒有定義key功能和轉換列表背部設置更簡單的解決方案:

print(dict((tuple(g[0] for g in group), group_key) for 
      (group_key, group) in itertools.groupby(sorted(A.items(), 
                  key=lambda x: sorted(list(x[1]))), 
                key=lambda x: x[1]))) 
5

我會進行轉型兩遍:

>>> A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

# First pass: Create a reverse one-to-many mapping. 
# The original set() value gets converted to a hashable frozenset() 
# and used as a key. The original scalar string key gets accumulated 
# in a list to track the multiple occurrences. 
>>> reverse = {} 
>>> for key, value in A.items(): 
     reverse.setdefault(frozenset(value), []).append(key) 

# Second pass: reverse the keys and values. The list of matching 
# values gets converted to a hashable tuple (as specified by the OP) 
# and the frozenset() gets restored back to the original set() type. 
>>> {tuple(value) : set(key) for key, value in reverse.items()} 
{('E2', 'E5'): {'5', '7'}, ('E3', 'E8'): {'8', '4'}} 

這給出了OP所期望的輸出。

請注意,輸入字典沒有保證的順序,也沒有原始輸入中的任何集合。因此,輸出不能保證條款的順序。

1

下面是我使用comprehensions進行的工作。只需要兩個中間步驟並僅使用內置數據類型。

# get unique values from original dict 
targ_values = set([tuple(v) for v in A.values()]) 

# build lists of original keys that match the temp_keys 
targ_values = {targ_value:[orig_key for orig_key, orig_value in A.items() if tuple(orig_value) == targ_value] for targ_value in targ_values} 

# reverse the order of keys & values and convert types to get desired output 
output = {tuple(v):set(k) for k, v in targ_values.items()} 
相關問題