Cleaning up a nested dictionary

383 views
Skip to first unread message

Simen Chris

unread,
Oct 30, 2013, 7:41:07 AM10/30/13
to python_in...@googlegroups.com


Hey guys, I often use dictionary in my functions to store and return created elements, however, it is really a pain to deal with if something in the dictionary doesn't exist. So I would like to have a function that goes through all of the elements in a dictionary, and if it finds object's that doesn't exists it should remove the values from the dictionary, and if it finds empty keys, it should delete them also.
 
Here's what I got so far:
#This is my dictionary
myDict
['objects']:  [('pSphere1'),
                     
('pSphere2'),
                   
[('pCube1'), ('pCube2'), ('pCube3')],
                   
[[('loc1'), ('loc2')], [('obj1'), ('obj2')]],
myDict
['nodes']:    [('pointConstraint1'),
                     
('pointConstraint2'),
                     
('pointConstraint3'),
                     
#I want to go through each item in the dictionary
for key, val in myDict.iteritems():
   
#If the current value is a list
   
if isinstance(val, list) == True:
       
#For each item in the list
       
for valLoop1 in val:
           
#If the current value is a list
           
if isinstance(valLoop1, list) == True:
               
#For each item in the list
               
for valLoop2 in valLoop1:
                 
#If the current value is a list
                 
if isinstance(valLoop2, list) == True:
                   
#And this goes on and on
                 
#If the current item is not a list
                 
else:
                   
#If the object doesn't exist
                   
if not cmds.objExists(val):
                     
#Pop the value out from the dictionary
                     
#Don't know how to do this yet
           
#If the current item is not a list
           
else:
             
#If the object doesn't exist
             
if not cmds.objExists(val):
               
#Pop the value out from the dictionary
               
#Don't know how to do this yet
   
#If the current item is not a list
   
else:
     
#If the object doesn't exist
     
if not cmds.objExists(val):
       
#Pop the value out from the dictionary
       
#Don't know how to do this yet

http://pastebin.com/2Q6dzLut
 
This is pretty ugly, how many lists it supports is dependant on how many isinstances I write.. Also if I find an object that doesn't exist, I don't know how to pop that specific value from the dictionary, and also if it finds empty keys..
 
 
Does anyone have any tips or hints on this?

damon shelton

unread,
Oct 30, 2013, 11:43:13 AM10/30/13
to python_in...@googlegroups.com

Use the get function and provide a default value where necessary.  Clearing out stuff would just be adding time to your processing.

foo = mydict.get(key, None)

Do that once then use the variable instead of getting the key again. No need to over complicate your code

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/df9f7cba-cc97-417e-b084-da18c99a2485%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Justin Israel

unread,
Oct 30, 2013, 3:15:13 PM10/30/13
to python_in...@googlegroups.com

You have single element tuples in your lists. Do you want to remove the tuple from the list if its single member does not exist, or remove the single item leaving an empty tuple? Will there ever be more than one element in the tuple? Is this the complete example of the data structure and the code doesn't have to handle any other variations?

Simen Chris

unread,
Nov 5, 2013, 5:13:42 AM11/5/13
to python_in...@googlegroups.com
Sorry for the delayed response guys
 
damonshelton: I couldn't get that to work, I'm getting # Error: NameError: file <maya console> line 1: name 'key' is not defined #
Justin Israel: Ideally I would like to remove the entire tuple from the list if it doesn't have any members, but just removing each single item that doesn't exists would work for me also. Yeah that's the tricky part, this isn't always the complete data structure of the dictionaries, if possible I would like it to work on dictionaries with other variations.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Justin Israel

unread,
Nov 5, 2013, 6:23:30 AM11/5/13
to python_in...@googlegroups.com
You probably just want to google about recursive looping over data structures. i.e. here is one that deals with nested dictionaries:

Unfortunately, the more unpredictable your data structures are, the more work you have to put into handling the walking of the structure. Are you sure these unpredictable nested data structures are the most efficient way to store your data? I imagine if its difficult for you to efficiently walk it to clean it up, that it would be equally difficult for the users of your data structure? (Also, your data structure in your example isn't valid python).



To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/36f91e3e-89cb-405f-aef2-0ce0b228c0fc%40googlegroups.com.

Simen Chris

unread,
Nov 5, 2013, 6:59:24 AM11/5/13
to python_in...@googlegroups.com
Thanks for the fast reply :)
 
I'm not sure if this is the most efficient way to store the data, actually I'm pretty sure it's among the worst, heh :p The reason why I'm storing in a dictionary is that I have some pretty large functions, and I want to be able to go in and get any object created within the function after it has run, so I thought dictionaries was the most readable way to do it, do you have any other suggestions?
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Paul Molodowitch

unread,
Nov 5, 2013, 10:03:28 AM11/5/13
to python_inside_maya
I'm not sure if this is the most efficient way to store the data, actually I'm pretty sure it's among the worst, heh :p The reason why I'm storing in a dictionary is that I have some pretty large functions, and I want to be able to go in and get any object created within the function after it has run, so I thought dictionaries was the most readable way to do it, do you have any other suggestions?

Try using object-oriented programming (OOP) - ie, classes.  The problem of associating a common set of data with a set of functions is one of the core issues that OOP was created to solve.  Unfortunately, this isn't necessarily an "easy" solution - learning how to properly use classes is something that will take practice - but it's well worth the effort, in my opinion.

Also - at a guess, you might also want to try breaking your "pretty large functions" into several smaller ones, if possible...

- Paul

Justin Israel

unread,
Nov 5, 2013, 2:11:46 PM11/5/13
to python_in...@googlegroups.com

The problem for me, in giving a specific suggestion, is that you have said your dictionary structure is completely variable in both its nested depth and its composition of types. So this will make it difficult to use in every function you give it to since any of them will need to scan through it to find something.
It would be much easier on you to figure out what data you need to store and what it will look like. As Paul suggested, you may find it more manageable to keep the data in multiple fields of a custom class, with methods that help to read and write to the structure.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAAssL7bEtFkgWN5W9eccGi6OYNeEMCD0%3D7i5To9Ehdr4d6gC_Q%40mail.gmail.com.

Simen Chris

unread,
Nov 8, 2013, 4:01:04 AM11/8/13
to python_in...@googlegroups.com
Thanks guys, I understand :) I've tried to write down some example code to illustrate what I'm trying to do, one where I've done it the way I've done here, and one where I've tried to inherit from classes. It isn't much difference, and I still don't know how to do this without using dictionaries :/
 
Here's the code without using inheritance: http://pastebin.com/f68x6x14
Here's the code where I've tried to inherit from classes: http://pastebin.com/7h6tk49B
 
I was hoping you could have a look at my code and give me some tips, I'd really appreciate that as I really struggle to wrap my head around this :/

On Tuesday, November 5, 2013 8:11:46 PM UTC+1, Justin Israel wrote:

The problem for me, in giving a specific suggestion, is that you have said your dictionary structure is completely variable in both its nested depth and its composition of types. So this will make it difficult to use in every function you give it to since any of them will need to scan through it to find something.
It would be much easier on you to figure out what data you need to store and what it will look like. As Paul suggested, you may find it more manageable to keep the data in multiple fields of a custom class, with methods that help to read and write to the structure.

On Nov 6, 2013 4:03 AM, "Paul Molodowitch" <elro...@gmail.com> wrote:
I'm not sure if this is the most efficient way to store the data, actually I'm pretty sure it's among the worst, heh :p The reason why I'm storing in a dictionary is that I have some pretty large functions, and I want to be able to go in and get any object created within the function after it has run, so I thought dictionaries was the most readable way to do it, do you have any other suggestions?

Try using object-oriented programming (OOP) - ie, classes.  The problem of associating a common set of data with a set of functions is one of the core issues that OOP was created to solve.  Unfortunately, this isn't necessarily an "easy" solution - learning how to properly use classes is something that will take practice - but it's well worth the effort, in my opinion.

Also - at a guess, you might also want to try breaking your "pretty large functions" into several smaller ones, if possible...

- Paul

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Justin Israel

unread,
Nov 8, 2013, 5:02:24 PM11/8/13
to python_in...@googlegroups.com
Now that I'm seeing some usage of your structure, it actually does seem like its a pretty predictable dictionary. Its just some top level keys, each with a list value of objects. In terms of wanting to break those up into discreet data structures, you could just get rid of the dictionary and make use of attributes on your rig class. That ends up just being 3 lists (joints, groups, ikHand). Pretty easy to manage, and no recursive dictionary action needed here (unless there is more to the story that isn't in the code examples).

I didn't really flesh out the entire behavior for you, to make defining subclasses of the Rig more streamlined, but here is an example of one way you could structure the base rig class to use attributes instead of a dictionary:


You will notice that I renamed your method to build() and it doesn't need to return anything. Your data is accessible on the public attributes of your rig instance. I also included an example of how you could wrap your joints into a Limb class, to make it easier to manage the sets instead of having to do hard-to-follow indexing into a big list. With these kinds of abstractions, you could add logic to manage them, such as wrapping in cmd calls to get info about the joints, or deleting them as needed. I think it is a lot easier to reason about your data when they are broken up into discreet manageable structures that don't require a big loop of different logic over the members. Limbs know what to do with their joints (if you extend the logic of the Limb class).





To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/eda1a162-1fdb-44fe-b0bc-7ff6539ffd5a%40googlegroups.com.

Simen Chris

unread,
Nov 11, 2013, 3:46:52 AM11/11/13
to python_in...@googlegroups.com
You sir, are awesome! Thank you so much! :D One quick question, what are the @property decorators for?

On Friday, November 8, 2013 11:02:24 PM UTC+1, Justin Israel wrote:
Now that I'm seeing some usage of your structure, it actually does seem like its a pretty predictable dictionary. Its just some top level keys, each with a list value of objects. In terms of wanting to break those up into discreet data structures, you could just get rid of the dictionary and make use of attributes on your rig class. That ends up just being 3 lists (joints, groups, ikHand). Pretty easy to manage, and no recursive dictionary action needed here (unless there is more to the story that isn't in the code examples).

I didn't really flesh out the entire behavior for you, to make defining subclasses of the Rig more streamlined, but here is an example of one way you could structure the base rig class to use attributes instead of a dictionary:


You will notice that I renamed your method to build() and it doesn't need to return anything. Your data is accessible on the public attributes of your rig instance. I also included an example of how you could wrap your joints into a Limb class, to make it easier to manage the sets instead of having to do hard-to-follow indexing into a big list. With these kinds of abstractions, you could add logic to manage them, such as wrapping in cmd calls to get info about the joints, or deleting them as needed. I think it is a lot easier to reason about your data when they are broken up into discreet manageable structures that don't require a big loop of different logic over the members. Limbs know what to do with their joints (if you extend the logic of the Limb class).



On Fri, Nov 8, 2013 at 10:01 PM, Simen Chris <simch...@gmail.com> wrote:
Thanks guys, I understand :) I've tried to write down some example code to illustrate what I'm trying to do, one where I've done it the way I've done here, and one where I've tried to inherit from classes. It isn't much difference, and I still don't know how to do this without using dictionaries :/
 
Here's the code without using inheritance: http://pastebin.com/f68x6x14
Here's the code where I've tried to inherit from classes: http://pastebin.com/7h6tk49B
 
I was hoping you could have a look at my code and give me some tips, I'd really appreciate that as I really struggle to wrap my head around this :/

On Tuesday, November 5, 2013 8:11:46 PM UTC+1, Justin Israel wrote:

The problem for me, in giving a specific suggestion, is that you have said your dictionary structure is completely variable in both its nested depth and its composition of types. So this will make it difficult to use in every function you give it to since any of them will need to scan through it to find something.
It would be much easier on you to figure out what data you need to store and what it will look like. As Paul suggested, you may find it more manageable to keep the data in multiple fields of a custom class, with methods that help to read and write to the structure.

On Nov 6, 2013 4:03 AM, "Paul Molodowitch" <elro...@gmail.com> wrote:
I'm not sure if this is the most efficient way to store the data, actually I'm pretty sure it's among the worst, heh :p The reason why I'm storing in a dictionary is that I have some pretty large functions, and I want to be able to go in and get any object created within the function after it has run, so I thought dictionaries was the most readable way to do it, do you have any other suggestions?

Try using object-oriented programming (OOP) - ie, classes.  The problem of associating a common set of data with a set of functions is one of the core issues that OOP was created to solve.  Unfortunately, this isn't necessarily an "easy" solution - learning how to properly use classes is something that will take practice - but it's well worth the effort, in my opinion.

Also - at a guess, you might also want to try breaking your "pretty large functions" into several smaller ones, if possible...

- Paul

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Justin Israel

unread,
Nov 11, 2013, 4:11:08 AM11/11/13
to python_in...@googlegroups.com
It's a builtin python function/decorator:

A computed property acts like a normal attribute, but under the hood uses a getter/setter/deleter. Before the decorator, the older way was to create your individual getter/setter methods and then assign a property(). But the decorator does it all for you. You can do stuff like lazy-evaluation where you don't compute the value until it is called, and then cache it from then on:

@property 
def value(self):
    if self.__value is None:
        self.__value = computeTheValue()
    return self.__value

They are useful when you want to represent them just like normal attributes. 



To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/82df4de0-4bfe-43a4-b47a-dff2ad7a0710%40googlegroups.com.

Simen Chris

unread,
Nov 12, 2013, 6:48:30 AM11/12/13
to python_in...@googlegroups.com
Thanks again Justin, I really appreciate it! :)

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages