如何制作嵌套字典并动态附加数据

时间:2012-01-09 13:40:09

标签: python dictionary nested maya

我有一个循环给我三个变量

matteGroup
matteName
object

我想制作一个嵌套的dicionary,其中包含所有数据:

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 个答案:

答案 0 :(得分:6)

如果我已正确理解您的要求:

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)

答案 1 :(得分:4)

尝试这样的事情

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 :(得分:2)

查看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)

答案 3 :(得分:1)

如果速度是一个问题,你可以利用try / except子句来尝试首先填充你的数据,而不是检查项目是否存在,然后每次通过循环添加它

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]

对于第一次尝试/除外,如果节点上不存在attr,最好放置maya抛出的任何异常(现在没有maya打开,所以我无法将其放入.. )。这基本上检查attr并且如果attr不存在则继续到下一个obj。你可以将它们放在那里,而不是每个都有自己的try / except,因为如果它们不存在则应该出错。

第二次尝试/除了检查matteGroup是否在你的dict的顶层。如果不是,那么你知道matteName和obj的列表也不在你的数据结构中,所以它添加它们并继续到下一个obj

第三次尝试/除了尝试将obj附加到matteName dict项目的列表。如果你在这里得到一个keyError,这意味着matteName不在你的matteGroup dict中,所以它然后添加它并创建列表,当前obj作为该列表中的第一项。

因此,就速度而言,数据结构中存在任何时间项,您添加到该数据项的下一个obj基本上只需添加,而无需测试是否所有其他数据结构都已到位添加它,使你的循环更快进入循环你去(假设有很多节点共享matteGroups和/或matteNames)

答案 4 :(得分:0)

由于腌制对象的问题(使用了先前的一些答案),我也尝试解决此问题。这是为我动态地向两个不同的子词典级别添加新键的方法:

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

此解决方案似乎只能处理两个级别的嵌套。