【问题标题】:How to make a nested dictionary and dynamically append data如何制作嵌套字典并动态追加数据
【发布时间】:2012-02-06 00:55:31
【问题描述】:

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

matteGroup
matteName
object

我想制作一个包含所有数据的嵌套字典,例如:

dictionary{matteGroup: {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)

有了这个,我分别得到了两个字典,但不是那么有用! 有什么提示吗?

谢谢

【问题讨论】:

    标签: python dictionary nested maya


    【解决方案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})})

          这个解决方案似乎只能处理两层嵌套。

          【讨论】:

            猜你喜欢
            • 2022-01-04
            • 1970-01-01
            • 2021-08-04
            • 2020-10-14
            • 2020-10-09
            • 1970-01-01
            • 2022-01-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多