2011-01-13 30 views
5
def revert_dict(d): 
    rd = {} 
    for key in d: 
     val = d[key] 
     if val in rd: 
      rd[val].append(key) 
     else: 
      rd[val] = [key] 
    return rd 

>>> revert_dict({'srvc3': '1', 'srvc2': '1', 'srvc1': '2'}) 
{'1': ['srvc3', 'srvc2'], '2': ['srvc1']} 

Điều này rõ ràng không phải là trao đổi đơn giản các khóa với giá trị: điều này sẽ ghi đè lên một số giá trị (như khóa mới) mà không phải là những gì tôi sau.thông minh hơn "đảo ngược" của một từ điển trong python (acc cho một số giá trị giống nhau)?

Nếu 2 hoặc nhiều giá trị giống nhau cho các khóa khác nhau, các phím được cho là được nhóm trong danh sách.

Chức năng trên hoạt động, nhưng tôi tự hỏi có cách nào thông minh hơn/nhanh hơn không?

+0

Nó được một lúc kể từ khi tôi đã sử dụng Python, nhưng có lẽ có điều gì đó bạn có thể làm với 'setdefault()' trên dict , để thu gọn 4 dòng của câu lệnh if thành 1? – Ken

+1

chúng ta có thể giả định rằng các giá trị của từ điển ban đầu là không thay đổi (đủ điều kiện là khóa), hoặc nó có thể là danh sách như vậy? Nói cách khác, bạn có muốn chức năng không thể đảo ngược? Tôi đoán không, như bạn không phải là, nhưng nó cũng có thể là một lỗi trong việc thực hiện hiện tại. – kriss

Trả lời

8

Điều đó có vẻ khá tốt. Bạn có thể đơn giản hóa nó một chút bằng cách sử dụng defaultdict:

import collections 

def revert_dict(d): 
    rd = collections.defaultdict(list) 

    for key, value in d.iteritems(): 
     rd[value].append(key) 

    return rd 
+0

+1 Tôi sẽ đăng một cái gì đó gần như giống hệt nhau. Lưu ý rằng điều này không nhất thiết phải nhanh hơn (như trong, thời gian thực dành cho nó) nhưng có cùng thời gian và không gian phức tạp và bất kỳ sự khác biệt thực sự nào sẽ không thể phủ nhận được. – delnan

+0

+1. Tôi vừa đăng một câu trả lời gần như giống hệt nhau, sau đó xóa nó :) –

+0

không có nhu cầu tuyệt đối của việc nhập defaultdict() – eyquem

0

Một cách tiếp cận khác. Không chắc chắn nếu điều này là nhanh hơn (tôi nghi ngờ rằng).

from itertools import groupby 

old_dict = {'srvc3': '1', 'srvc2': '1', 'srvc1': '2'} 
funcval = d.__getitem__ 
new_dict = dict((val, list(keys)) for val, keys in \ 
       groupby(sorted(d.iterkeys(), key=funcval), funcval)) 

# new_dict: 
# {'1': ['srvc3', 'srvc2'], '2': ['srvc1']} 

mã ban đầu của bạn chắc chắn không phải là xấu (có thể đọc được) mặc dù tôi có lẽ đã viết nó như thế này (ưu tiên chủ yếu là cá nhân, thực sự):

def revert_dict(d): 
    rd = {} 
    for key, val in d.items(): 
     try: 
      rd[val].append(key) 
     except KeyError: 
      rd[val] = [key] 
    return rd 
0

Có lẽ không phải là hiệu quả, nhưng:

ks, vs = old_dict.items() 
new_dict = dict((v, [k for k in ks if old_dict[k] == v]) for v in set(vs)) 
0
def invertDictionary(d): 
    rd = {} 
    for x,y in d.iteritems(): 
      if y in rd.keys(): 
        rd[y].append(x) 
      else: 
        rd[y] = [x] 
    return rd 

Tôi thấy điều này dễ đọc nhất với bản thân mình. Bất kỳ nhược điểm nào?

0
def revert_dict(d): 
    rd = {} 
    for key,val in d.iteritems(): 
     rd[val] = rd.get(val,[]) + [key] 
    return rd 


print revert_dict({'srvc3': '1', 'srvc2': '1', 'srvc1': '2', 
      'srvc4': '8', 'srvc5': '2', 'srvc6': '2', 
      'srvc7': '77', 'srvc8': '1', 'srvc9': '2', 
      'srvc10': '3', 'srvc11': '1'}) 

kết quả

{'1': ['srvc11', 'srvc3', 'srvc2', 'srvc8'], '77': ['srvc7'], '3': ['srvc10'], '2': ['srvc6', 'srvc5', 'srvc1', 'srvc9'], '8': ['srvc4']} 

thêm:

def revert_dict(d): 
    rd = {} 
    for key,val in d.iteritems(): 
     rd[val] = rd[val]+ [key] if val in rd else [key] 
    return rd 
Các vấn đề liên quan