如何制作嵌套字典并动态追加数据
Posted
技术标签:
【中文标题】如何制作嵌套字典并动态追加数据【英文标题】:How to make a nested dictionary and dynamically append data 【发布时间】:2012-02-06 00:55:31 【问题描述】:我有一个循环给我三个变量
matteGroup
matteName
object
我想制作一个包含所有数据的嵌套字典,例如:
dictionarymatteGroup: matteName: obj1, obj2, ob3
我正在一一检查对象,所以如果matteGroup
不存在,我想创建它,如果它不存在则创建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)
有了这个,我分别得到了两个字典,但不是那么有用! 有什么提示吗?
谢谢
【问题讨论】:
【参考方案1】:试试这样的
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】:如果我正确理解了您的要求:
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)
【讨论】:
【参考方案3】:查看collections
模块中的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)
【讨论】:
【参考方案4】:如果速度是一个问题,您可以使用 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 并继续到下一个 obj 如果 attr 不存在。您可以将它们都放在那里,而不是每个都有自己的 try/except,因为如果其中任何一个都不存在,它应该会出错。
第二个 try/except 是检查 matteGroup 是否在您的 dict 的顶层。如果不是,那么您知道 matteName 和 obj 列表也不在您的数据结构中,因此它会添加它们并继续到下一个 obj
第三个 try/except 尝试将 obj 附加到 matteName dict 项目的列表中。如果您在此处收到 keyError,则表示 matteName 不在您的 matteGroup 字典中,因此它会添加它并创建列表,其中当前 obj 作为该列表中的第一项。
因此,就速度而言,只要数据结构中存在项目,您添加到该数据项目的下一个 obj 基本上只会被添加,而无需测试之前是否所有其他数据结构都已到位添加它,使您的循环越深入循环越快(假设有很多节点共享 matteGroups 和/或 matteNames)
【讨论】:
您也可以组合最后两个 try/except 子句,然后尝试先将 obj 附加到列表中...不过确实有点困难,因为您不知道哪个 dict不包含您要访问的密钥,因此如果您真的想要,您必须使用嵌套的 try/except 子句来解释这一点...... aaaaaa 我刚刚意识到这个问题来自近 5 年半前,所以我怀疑有人会看这个答案,呵呵。【参考方案5】:由于我的对象腌制问题,使用了以前的一些答案,我也尝试解决这个问题。这对我来说是动态添加新键到两个不同的子级字典的方法:
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))
这个解决方案似乎只能处理两层嵌套。
【讨论】:
以上是关于如何制作嵌套字典并动态追加数据的主要内容,如果未能解决你的问题,请参考以下文章