How to make a nested dictionary and dynamically append data

前端 未结 5 1099
闹比i
闹比i 2021-01-13 02:16

I have a loop giving me three variables

matteGroup
matteName
object

I would like to make a nested dicionary holding all the data like:

相关标签:
5条回答
  • 2021-01-13 02:21

    Provided I've understood your requirements correctly:

    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)
    
    0 讨论(0)
  • 2021-01-13 02:22

    if speed is a concern, you could utilize try/except clauses to just try to populate your data first rather than checking if items exist and then adding it each time through the loop

    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]
    

    for the first try/except, it would be best to put whatever exception maya throws if an attr doesn't exist on a node (don't have maya open right now, so I couldn't put that in...). This essentially checks for the attr and continues to the next obj if the attr isn't there. You can put them both in there instead of each having their own try/except, because it should error if either doesn't exist anyway.

    the second try/except is checking if the matteGroup is in the top level of your dict. If it isn't, then you know the matteName and list of obj's isn't in your data structure either, so it adds them and continues to the next obj

    the third try/except tries to append the obj to the matteName dict item's list. If you get a keyError here, it means that the matteName isn't in your matteGroup dict, so it then adds it and creates the list with the current obj as the first item in that list.

    So, as far as speed is concerned, any time items exist in your data structure, the next obj you add to that data item will essentially just get added without having to test if all of the other data structure is in place before adding it, making your loop go faster the further into the loop you go (provided there are a lot of nodes sharing matteGroups and/or matteNames)

    0 讨论(0)
  • 2021-01-13 02:30

    try something like this

    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)
    
    0 讨论(0)
  • 2021-01-13 02:32

    Due to an issue with pickling my object, that used some of the previous answers, I tried to solve this as well. This is what worked for me for dynamically adding new keys to two different sub levels of dictionaries:

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

    This solution seems to be only able to handle two levels of nesting.

    0 讨论(0)
  • 2021-01-13 02:45

    Look at the defaultdict in the collections module.

    Here's a simple example that looks like what you're going for:

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

    So, you should just need this:

    if mc.objExists(obj + ('.matteGroup')):
       matteGroup = mc.getAttr(obj + ('.matteGroup'))
       matteName = mc.getAttr(obj + ('.matteName'))
       dizGroup[matteGroup][matteName].append(obj)
    
    0 讨论(0)
提交回复
热议问题