Извлекать повторяющиеся значения из словаря - PullRequest
5 голосов
/ 21 марта 2012

Я пытаюсь найти способ удаления дубликатов шейдеров в Maya с помощью словарей Python.

Вот что я делаю:

Я хочу поместить все шейдеры Maya в словарьв качестве ключей и поместите соответствующий файл текстуры в качестве значения.Затем я хочу, чтобы скрипт прошел через словарь и нашел все ключи с одинаковым значением и поместил их в массив или другой словарь.

Это в основном то, что у меня есть сейчас:

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

duplicate_shaders_dict = {}`

как теперь я могу пройти через этот словарь, чтобы скомпилировать другой словарь, который выглядит примерно так:

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

И сложная часть, так как есть дубликаты, я хочу, чтобы скрипт был skip the original key, поэтому он неНе попадайте в дубликат словаря шейдеров.

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

Я бы, наверное, сделал что-то подобное.Во-первых, создайте обратный словарь:

>>> 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']})

Это в основном инвертирует словарь путем циклического перебора каждого ключа, пары значений и добавления ключа к списку, связанному со значением.

Затем разделите это:

>>> 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'}

Хмм.Это предполагает, что файлы текстур являются хэшируемыми и могут служить в качестве ключей словаря.Если нет, то мне придется обойти это.Кроме того, поскольку, как отмечает @freespace, здесь нет упорядочивания, если бы вы хотели определенный порядок, нам пришлось бы перебирать отсортированные ключи или тому подобное.

-

Обновление: я не сделалочень нравится выше.Более короткая версия на основе itertools:

>>> 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'}
3 голосов
/ 21 марта 2012

Одно простое решение - перевернуть словарь.Дано:

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

Вы можете изменить это так:

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

Что дает вам:

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

И если вы отмените это, у вас есть оригиналсловарь с удаленными дубликатами:

>>> d = dict((v,k) for k,v in r.iteritems())
>>> d
{'b': 'somePath', 'd': 'differentPath'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...