Как сделать вложенный словарь и динамически добавлять данные - PullRequest
5 голосов
/ 09 января 2012

У меня есть цикл, дающий мне три переменные

matteGroup
matteName
object

Я хотел бы создать вложенный дисионар, содержащий все данные, например:

dictionary{matteGroup: {matteName: obj1, obj2, ob3} }

Я проверяю объекты один за другим, поэтому я хотел бы создать matteGroup, если он не существует, создать matteName, если он не exixst, а затем создать или добавить имя объекта. Я пробовал множество решений, таких как обычные словари, defaultdict и некоторые пользовательские классы, которые я нашел в сети, но я не смог сделать это должным образом. У меня хорошая вложенность, которую я не могу добавить, или наоборот.

Это цикл

    dizGroup = {}
    dizName = {}

    for obj in mc.ls(type='transform'):
        if mc.objExists(obj + ('.matteGroup')):
            matteGroup = mc.getAttr(obj + ('.matteGroup'))
            matteName = mc.getAttr(obj + ('.matteName'))

            if matteGroup not in dizGroup:
                dizGroup[matteGroup] = list()
            dizGroup[matteGroup].append(matteName)

            if matteName not in dizName:
                dizName[matteName] = list()
            dizName[matteName].append(obj)

при этом я получаю два словаря по отдельности, но это не так полезно! Любой намек?

Спасибо

Ответы [ 5 ]

7 голосов
/ 09 января 2012

При условии, что я правильно понял ваши требования:

In [25]: from collections import defaultdict

In [26]: d = defaultdict(lambda: defaultdict(list))

In [30]: for group, name, obj in [('g1','n1','o1'),('g1','n2','o2'),('g1','n1','o3'),('g2','n1','o4')]:
   ....:     d[group][name].append(obj)
4 голосов
/ 09 января 2012

попробуйте что-то вроде этого

dizGroup = {}

for obj in mc.ls(type='transform'):
    if mc.objExists(obj + ('.matteGroup')):
        matteGroup = mc.getAttr(obj + ('.matteGroup'))
        matteName = mc.getAttr(obj + ('.matteName'))

        if matteGroup not in dizGroup:
            dizGroup[matteGroup] = {}

        if matteName not in dizGroup[matteGroup]:
            dizGroup[matteGroup][matteName] = []

        dizGroup[matteGroup][matteName].append(obj)
2 голосов
/ 09 января 2012

Посмотрите на defaultdict в модуле collections.

Вот простой пример, который выглядит так, как вы собираетесь:

>>> from collections import defaultdict
>>> dizGroup = defaultdict(lambda:defaultdict(list))
>>> dizGroup['group1']['name1'].append(1)
>>> dizGroup['group1']['name1'].append(2)
>>> dizGroup['group1']['name1'].append(3)
>>> dizGroup['group1']['name2'].append(4)
>>> dizGroup['group1']['name2'].append(5)
>>> dizGroup['group2']['name1'].append(6)
>>> dizGroup
defaultdict(<function <lambda> at 0x7ffcb5ace9b0>, {'group1': defaultdict(<type 'list'>, {'name2': [4, 5], 'name1': [1, 2, 3]}), 'group2': defaultdict(<type 'list'>, {'name1': [6]})})

Итак, вам просто нужно это:

if mc.objExists(obj + ('.matteGroup')):
   matteGroup = mc.getAttr(obj + ('.matteGroup'))
   matteName = mc.getAttr(obj + ('.matteName'))
   dizGroup[matteGroup][matteName].append(obj)
1 голос
/ 11 июня 2017

, если скорость имеет значение, вы можете использовать операторы try / исключением, чтобы просто попытаться сначала заполнить данные, а не проверять, существуют ли элементы, а затем добавлять их каждый раз в цикле

diz = {}

for obj in mc.ls(type='transform'):
    try:
        matteGroup = mc.getAttr('%s.matteGroup' %obj)
        matteName = mc.getAttr('%s.matteName' %obj)
    except Exception:
        continue

    try:
        diz[matteGroup]
    except KeyError:
        diz[matteGroup] = {matteName : [obj]}
        continue

    try:
        diz[matteGroup][matteName].append(obj)
    except KeyError:
        diz[matteGroup][matteName] = [obj]

длясначала попробуйте / исключите, было бы лучше поместить любое исключение, которое выдает maya, если attr не существует на узле (у меня сейчас нет открытого maya, так что я не могу это вставить ...).Это, по сути, проверяет attr и переходит к следующему объекту, если его нет.Вы можете поместить их туда вместо того, чтобы у каждого была своя собственная попытка / исключение, потому что должно произойти ошибка, если любой из них все равно не существует.

вторая попытка / исключение проверяет, находится ли группа matteGroup на верхнем уровневашего диктата.Если это не так, то вы знаете, что matteName и список объектов не входят в вашу структуру данных, поэтому он добавляет их и продолжает к следующему объекту

с третьей попытки / кроме попытки добавить объект.в список элементов DECT matteName.Если вы получили здесь keyError, это означает, что matteName отсутствует в вашем файле matteGroup, поэтому он добавляет его и создает список с текущим obj в качестве первого элемента в этом списке.

Итак, какЧто касается скорости, то всякий раз, когда элементы существуют в вашей структуре данных, следующий объект, который вы добавляете к этому элементу данных, будет просто добавляться без необходимости проверять, все ли остальные структуры данных на месте перед его добавлением, что делает ваш циклИдите быстрее, чем дальше в цикле, который вы идете (при условии, что есть много узлов, совместно использующих matteGroups и / или matteNames)

0 голосов
/ 30 октября 2018

Из-за проблемы с травлением моего объекта, в которой использовались некоторые из предыдущих ответов, я тоже пытался решить эту проблему. Вот что сработало для меня для динамического добавления новых ключей в два разных подуровня словарей:

from collections import defaultdict
test = defaultdict(defaultdict)
test["level1"]["level2"] = 1
test["level1"]["level2_second"] = 2
print(test)

defaultdict (, {'level1': defaultdict (None, {'level2': 1, 'level2_second': 2})})

Похоже, что это решение может обрабатывать только два уровня вложенности.

...