2012-01-09 40 views
4

我有一个循环给我三个变量如何使嵌套的字典和动态数据追加

matteGroup 
matteName 
object 

我想作一个嵌套dicionary保存所有数据,如到:

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

我我正在逐个检查对象,因此如果它不存在,我想创建matteGroup,如果它不exixst,则创建matteName,然后创建或追加对象的名称。 我尝试了很多像普通字典,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) 

这个我分别得到两本词典,但不是那么有用! 任何提示?

感谢

回答

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

提供我理解正确的话你的要求:collections模块中

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

看那defaultdict

这里有一个简单的例子,看起来像你要什么:

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

如果速度是一个问题,你可以利用的尝试/除了条款,只是试图填充您的数据,而不是检查项目是否存在,然后每次通过循环添加它

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并继续到下一个obj,如果attr不在那里的话。你可以把它们放在那里而不是每个都有自己的尝试/除外,因为如果任何一个都不存在,它应该会出错。

第二次尝试/除了检查matteGroup是否在您的字典的顶层。如果不是,那么你知道matteName和obj列表不在你的数据结构中,所以它将它们添加并继续到下一个目标,除非尝试将obj追加到matteName字典项目的列表。如果你在这里得到一个keyError,这意味着matteName不在你的matteGroup字典中,所以它会添加它,并创建带有当前obj的列表作为该列表中的第一项。因此,就速度而言,数据结构中存在任何时间项,那么添加到该数据项的下一个obj基本上只会被添加,而不必测试是否所有其他数据结构都已就位在添加它之前,让你的循环更快进入你要去的循环(假设有很多节点共享matteGroups和/或matteNames)

+0

你也可以结合最后两个try/except子句,并试图追加首先是列表中的obj ...但它确实有些困难,因为你不知道哪个字典不包含你想要访问的密钥,所以你必须考虑嵌套的try /除了条款,如果你真的想... ... aaaaaaand我刚刚意识到这个问题是从近5年前,所以我怀疑你甚至会看这个答案,嘿。 – 2017-06-11 03:40:07