我有一个循环给我三个变量
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)
用这个我分别得到两个词典,但是没那么有用! 任何提示?
由于
答案 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})})
此解决方案似乎只能处理两个级别的嵌套。