2012-03-21 21 views
5

Tôi đang cố gắng tìm cách xóa các trình tạo bóng trùng lặp trong Maya bằng cách sử dụng Từ điển Python.Trích xuất các giá trị trùng lặp từ một từ điển

Đây là những gì tôi đang làm:

Tôi muốn đặt tất cả shaders maya vào một cuốn từ điển như phím và đưa những file texture tương ứng như giá trị. Sau đó, tôi muốn tập lệnh chạy qua từ điển và tìm bất kỳ khóa nào có cùng giá trị và đặt chúng vào một mảng hoặc một từ điển khác.

này về cơ bản là những gì tôi có ngay bây giờ:

shaders_dict = {'a': somePath, 'b': somePath, 
       'c': differentPath, 'd': differentPath} 

duplicate_shaders_dict = {}` 

làm thế nào tôi bây giờ có thể chạy qua từ điển đó để biên dịch một từ điển mà trông giống như sau:

duplicate_shaders_dict = {'b':somePath, 'd':differentPath } 

Và phần khó khăn là vì có bản sao, tôi muốn tập lệnh thành skip the original key vì vậy nó cũng không được nhồi nhét vào từ điển bóng râm trùng lặp.

+3

Tôi giả định bằng "khóa gốc" nghĩa là 'a' trong ví dụ của bạn. Tôi muốn chỉ ra rằng từ điển không được đặt hàng và "khóa gốc" chỉ có thể có nghĩa là "lần đầu tiên gặp phải". – freespace

Trả lời

3

Một giải pháp đơn giản là đảo ngược từ điển. Đưa ra:

>>> d = {'a': 'somePath', 'b': 'somePath', 
... 'c': 'differentPath', 'd': 'differentPath'} 

Bạn có thể đảo ngược nó như thế này:

>>> r = dict((v,k) for k,v in d.iteritems()) 

nào mang đến cho bạn:

>>> r 
{'differentPath': 'd', 'somePath': 'b'} 

Và nếu bạn đảo ngược điều đó, bạn có từ điển ban đầu với bản sao loại bỏ:

>>> d = dict((v,k) for k,v in r.iteritems()) 
>>> d 
{'b': 'somePath', 'd': 'differentPath'} 
+0

và giá trị trùng lặp ở đâu? – juliomalegria

+0

Huh, bỏ lỡ phần đó. Điều này bắt đầu với phần "những gì tôi có" của câu hỏi và mang lại phần "những gì tôi muốn", vì vậy nó có thể là một nơi tốt để bắt đầu. – larsks

+0

Điều này có ý nghĩa: nhưng tôi không muốn chỉ cần loại bỏ các bản sao, tôi cần phải đặt chúng vào một biến khác để sau này tôi có thể hành động trên chúng và sau đó xóa chúng khỏi hiện trường –

4

Tôi sẽ pr làm điều gì đó như thế này. Trước tiên, hãy tạo từ điển ngược:

>>> from collections import defaultdict 
>>> 
>>> shaders_dict = {'a':'somePath', 'b':'somePath', 'c':'differentPath', 'd':'differentPath'} 
>>> 
>>> inverse_dict = defaultdict(list) 
>>> for k,v in shaders_dict.iteritems(): 
...  inverse_dict[v].append(k) 
... 
>>> inverse_dict 
defaultdict(<type 'list'>, {'differentPath': ['c', 'd'], 'somePath': ['a', 'b']}) 

Điều này về cơ bản sẽ đảo ngược từ điển bằng cách lặp qua mỗi cặp khóa, giá trị và thêm khóa vào danh sách được liên kết với giá trị.

Sau đó chia này:

>>> first_shaders_dict = {} 
>>> duplicate_shaders_dict = {} 
>>> for v, ks in inverse_dict.iteritems(): 
...  first, rest = ks[0], ks[1:] 
...  first_shaders_dict[first] = v 
...  for r in rest: 
...   duplicate_shaders_dict[r] = v 
... 
>>> first_shaders_dict 
{'a': 'somePath', 'c': 'differentPath'} 
>>> duplicate_shaders_dict 
{'b': 'somePath', 'd': 'differentPath'} 

Hmm. Điều này giả định rằng các tệp kết cấu có thể băm và do đó có thể dùng làm khóa từ điển. Nếu không, thì tôi phải làm việc đó. Ngoài ra, kể từ khi ghi chú @freespace không có thứ tự ở đây, nếu bạn muốn có một thứ tự cụ thể, chúng tôi sẽ phải lặp qua các phím được sắp xếp hoặc tương tự.

-

Cập nhật: Tôi không thích những điều trên. Phiên bản dựa trên itertools ngắn hơn:

>>> import itertools 
>>> shaders_dict = {'a':'somePath', 'b':'somePath', 'c':'differentPath', 'd':'differentPath'} 
>>> keys = sorted(sorted(shaders_dict),key=shaders_dict.get) 
>>> by_val = [(v, list(ks)) for v, ks in itertools.groupby(keys, shaders_dict.get)] 
>>> first_dict = dict((ks[0],v) for v,ks in by_val) 
>>> duplicate_dict = dict((k,v) for v,ks in by_val for k in ks[1:]) 
>>> first_dict 
{'a': 'somePath', 'c': 'differentPath'} 
>>> duplicate_dict 
{'b': 'somePath', 'd': 'differentPath'} 
+0

Cái này đã làm được! mặc dù đó là loại "phép thuật" đối với tôi. Tôi sẽ nghiên cứu giải pháp này. –

+0

+1 để cập nhật ... –

Các vấn đề liên quan