2014-01-27 72 views
0

我有這樣一本字典:Python的逆字典非唯一映射

dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 

,並希望逆這樣的:

dict2 = dict({1:['a','b','c'], 2:['a','b','c'], 3:['a','b'], 4:['b']}) 

這樣的問題:

Inverse Dict in Python \\ In-place dictionary inversion in Python

但我想這樣做與非唯一鍵,我不想就地轉換。我有一些代碼工作,但我想知道是否有字典理解的方式來做到這一點。

from collections import defaultdict 
dict2 = defaultdict(list) 
for i in dict1: 
    for j in dict1[i]: 
     dict2[j].append(i) 

我試過這個,但它只適用於獨特的映射。唯一的意思就是「對於每個值,只有一個關鍵值在其中列出」。如此獨特的映射:'1:[a],2:[b],3:[c] - > a:[1],b:[2],c:[3]'VS非唯一映射'1:並[a],2:[A,b],3:[b,C] - >一:[1,2],b:[2,3],C:[3]」

dict2 = {j: i for i in dict1 for j in dict1[i]} 

我想它一定是這樣的:

dict2 = {j: [i for i in dict1 if j in dict1[i]] for j in dict1[i]} # I know this doesn't work 

而且它不工作,好像這樣的理解是低效的。有沒有這樣做的有效的一種班輪方式?

+1

它不會對非唯一值工作,根據定義,在字典或哈希表鍵__unique__ – Oz123

+1

Python字典不支持重複鍵 - >''http:// stackoverflow.com/questions/10664856/make-dictionary-with-duplicate-keys-in-python' –

+0

我想我對「unique」的使用是不明確的。我所說的「獨特」是指如果原始字典具有從鍵 - >值的1-1映射。獨特的意思就是「對於每個價值,只有一個價值列出的關鍵」。如此獨特的映射:'1:[a],2:[b],3:[c] - > a:[1],b:[2],c:[3]'vs'1:[a] ,2:[a,b],3:[b,c] - > a:[1,2],b:[2,3],c:[3]'' – dantiston

回答

3

我想通了基於Vroomfondel的回答答案:

dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = {item: [key for key in dict1 if item in dict1[key]] for value in dict1.values() for item in value} 

這不是最快的,但它是一個襯墊,它是不是最慢提供的選項!

from timeit import timeit 

methods = [['Vroomfondel1', '''from collections import defaultdict 
import itertools 
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = defaultdict(list) 
for k,v in itertools.chain.from_iterable([itertools.product(vals,key) for key,vals in dict1.items()]): 
    dict2[k].append(v)'''], 

['Vroomfondel2', '''from collections import defaultdict 
import itertools 
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = defaultdict(list) 
[dict2[k].append(v) for k,v in itertools.chain.from_iterable([itertools.product(vals,key) for key,vals in dict1.items()])]'''], 


['***Vroomfondel2 mod', '''dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = {item: [key for key in dict1 if item in dict1[key]] for value in dict1.values() for item in value}'''], 

['mhlester1', '''dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = {} 
for key, values in dict1.items(): 
    for value in values: 
     dict2.setdefault(value, []).append(key)'''], 

['mhlester1 mod', '''from collections import defaultdict 
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = defaultdict(list) 
for key, values in dict1.items(): 
    for value in values: 
     dict2[value].append(key)'''], 

['mhlester2', '''from collections import defaultdict 
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = defaultdict(list) 
for key, values in dict1.items(): 
    for value in values: 
     dict2[value].append(key)'''], 

['initial', '''from collections import defaultdict 
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]} 
dict2 = defaultdict(list) 
for i in dict1: 
    for j in dict1[i]: 
     dict2[j].append(i)'''] 

] 

for method in methods: 
    print "% 15s" % (method[0]), '\t', timeit(method[1], number=10000) 

打印出:

Vroomfondel1  0.202519893646 
    Vroomfondel2  0.164724111557 
***Vroomfondel2 mod  0.114083051682 
     mhlester1  0.0599339008331 
    mhlester1 mod  0.091933965683 
     mhlester2  0.0900268554688 
     initial  0.0953099727631 
+0

如果第一個字典是:A = {1 :('a','b'),2 :('b','e','c'),3 :('a','f'), 4 :('c','d'),5 :('d','e','f')} with dict2 = {item:[A鍵中的鍵的鍵值,如果A [鍵]中的鍵值]在A.values()中的值爲item} print dict2最後得出:{'a':[1,3],'c':[2,4],'b':[1,2] e':[2,5],'d':[4,5],'f':[3,5]} –

4

標準dict

>>> dict2 = {} 
>>> for key, values in dict1.items(): 
...  for value in values: 
...    dict2.setdefault(value, []).append(key) 
... 
>>> dict2 
{1: ['a', 'c', 'b'], 2: ['a', 'c', 'b'], 3: ['a', 'b'], 4: ['b']} 

defaultdict

>>> dict2 = defaultdict(list) 
>>> for key, values in dict1.items(): 
...  for value in values: 
...    dict2[value].append(key) 
... 
>>> dict2 
{1: ['a', 'c', 'b'], 2: ['a', 'c', 'b'], 3: ['a', 'b'], 4: ['b']} 
+0

這與我發佈的代碼基本相同,並沒有解決我的任何問題。 – dantiston

+0

這給出了你想說的輸出。如果你想要一個不同的輸出,嘲笑它! – mhlester

2

作爲一個班輪(感謝mhlesters輸入),但馬馬虎虎的可讀性(而且只有工作,因爲在dict2值是可變的,因此默認返回對它們的引用):

import itertools 
[dict2.setdefault(k,[]).append(v) for k,v in itertools.chain.from_iterable([itertools.product(vals,[key]) for key,vals in dict1.items()])] 

或用一個for循環:

import collections 
import itertools 
dict2=collections.defaultdict(list) 
for k,v in itertools.chain.from_iterable([itertools.product(vals,[key]) for key,vals in dict1.items()]): 
    dict2[k].append(v)