Converting list entries in nested dictionaries into dictionary type

15 views
Skip to first unread message

yann19

unread,
Dec 11, 2018, 3:07:52 PM12/11/18
to Python Programming for Autodesk Maya
I apologize in advance as this is not much of a Maya question but I am trying to convert this 'list' within nested dictionaries into a  dictionary type.

I had a function where it ingests in a nested dictionary and allows me to sort the contents by a specified value eg. name.
This is a portion of it - 
return {k: {'entries': sorted([v1 for _,v1 in v['entries'].items()], key=lambda el: el['name'])} for k,v in dict_data.items()}

However, possibly because I am using [] which returns me a list type.

What I am expecting in the output is something as follow:
{'my test':
   
{
       
'entries': {
           
'name': 'running_slow_v001'
           
...
           
},
         
...
   
}
}

but I am getting:
{'my test':
   
{
       
'entries': [{
           
'name': 'running_slow_v001'
           
...
           
}],
         
...
   
}
}


I tried using `dict()` and tested the placement anywhere within the return sentence, it will returns me an error.
Appreciate in advance for any replies.

Daniele Dolci

unread,
Dec 11, 2018, 3:32:09 PM12/11/18
to Python Programming for Autodesk Maya
Dictionaries are basically hash maps and therefore are not ordered. You can't preserve the order of the entries in a dict, indeed when you use sort you are doing it on a list. There is something called ordered dictionary that you can check out, otherwise  you could use a list of tuples. I hope it helps. 

Justin Israel

unread,
Dec 11, 2018, 3:37:29 PM12/11/18
to python_in...@googlegroups.com
On Wed, Dec 12, 2018 at 9:07 AM yann19 <yang...@gmail.com> wrote:
I apologize in advance as this is not much of a Maya question but I am trying to convert this 'list' within nested dictionaries into a  dictionary type.

I had a function where it ingests in a nested dictionary and allows me to sort the contents by a specified value eg. name.
This is a portion of it - 
return {k: {'entries': sorted([v1 for _,v1 in v['entries'].items()], key=lambda el: el['name'])} for k,v in dict_data.items()}


This is a very difficult line to visually parse. At least if the key function were extracted to its own variable, and if you used v['entries'].values() then it would be a bit shorter and easier to read.
 
However, possibly because I am using [] which returns me a list type.

What I am expecting in the output is something as follow:
{'my test':
   
{
       
'entries': {
           
'name': 'running_slow_v001'
           
...
           
},
         
...
   
}
}

but I am getting:
{'my test':
   
{
       
'entries': [{
           
'name': 'running_slow_v001'
           
...
           
}],
         
...
   
}
}


I tried using `dict()` and tested the placement anywhere within the return sentence, it will returns me an error.
Appreciate in advance for any replies.

It sounds like your single line is too complicated if you are just trying to throw a dict() call into random places in the expression to see if it works. It might benefit you to unroll this into a proper for loop. But yea, the reason you are seeing a list is because sorted() takes an interable and returns a list. From the looks of your example output it appears that each value of v['entries'] is a dictionary. That means you will have to further iterate those values to combine them into a single dictionary. One more complex way to do it in a single line would be to replace the sorted() with:

    {k:v for k,v in intertools.chain.from_iterable(d.items() for d in v['entries'].values())}

But this only further complicates your already complex single line. This is equivalent to:

    entries = {}
    for d in v['entries'].values():
        entries.update(d)

But as I look at this formatting goal you mentioned, how do you plan to handle the collisions of the fields in each 'entries' dict value? Is each one going to have a 'name' field? If so, they are all going to overlay and the last key wins. The list format would preserve the individual fields of each entry.
 

--
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/8f6ab8cf-b239-4713-8ef7-3deeb86075dd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Justin Israel

unread,
Dec 11, 2018, 3:39:47 PM12/11/18
to python_in...@googlegroups.com
On Wed, Dec 12, 2018 at 9:32 AM Daniele Dolci <daniele...@gmail.com> wrote:
Dictionaries are basically hash maps and therefore are not ordered. You can't preserve the order of the entries in a dict, indeed when you use sort you are doing it on a list. There is something called ordered dictionary that you can check out, otherwise  you could use a list of tuples. I hope it helps. 

You are right, and I think I misread the intent from that line. It does look like the intended goal was to have an ordered dictionary based on the 'name' field of each dict value.
 


Il giorno martedì 11 dicembre 2018 21:07:52 UTC+1, yann19 ha scritto:
I apologize in advance as this is not much of a Maya question but I am trying to convert this 'list' within nested dictionaries into a  dictionary type.

I had a function where it ingests in a nested dictionary and allows me to sort the contents by a specified value eg. name.
This is a portion of it - 
return {k: {'entries': sorted([v1 for _,v1 in v['entries'].items()], key=lambda el: el['name'])} for k,v in dict_data.items()}

However, possibly because I am using [] which returns me a list type.

What I am expecting in the output is something as follow:
{'my test':
   
{
       
'entries': {
           
'name': 'running_slow_v001'
           
...
           
},
         
...
   
}
}

but I am getting:
{'my test':
   
{
       
'entries': [{
           
'name': 'running_slow_v001'
           
...
           
}],
         
...
   
}
}


I tried using `dict()` and tested the placement anywhere within the return sentence, it will returns me an error.
Appreciate in advance for any replies.

--
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.

yann19

unread,
Dec 11, 2018, 4:56:58 PM12/11/18
to Python Programming for Autodesk Maya
My bad, had thought I had added in my dictionary example.

And my actual codes:
from datetime import datetime

def sortedPage(d):
    return {k: {'elements': sorted([v1 for k1 ,v1 in v['elements'].items()], key=lambda el: datetime.strptime(el['data']['created'], '%d/%m/%y %H:%M'))} for k,v in d.items()}

output = {k: sortedPage(v) if k == 'pages' else v for k,v in test_dict.items()}
pprint(output)

I am trying to retain the whole contents of the dictionary to begin with but with sorting options based on a particular key/value.
However I just noticed that in the code, I am missing the unique ids..

Example - The output of returned code:
{'page_order': ['rotatingTest', 'zoomingTest', 'panningTest'],
 'pages': {'panningTest': {'elements': [{'data': {'created': '04/10/18 12:43',
                                                  'description': 'panning test for posZ',
                                                  'name': 'posePan_positionZ_v001',
                                                  'project': 'TEST',
                                                  'version': '1'},
                                         'name': 'posePan_positionZ_v001',
                                         'thumbnail': '/user_data/posePan_positionZ_v001/posePan_positionZ_v001.thumb.jpg',
                                         'type': 'PosedWidget',
                                         'uid': '7lyuri8g8u5ctwsa'}]},

Whereas what I am trying to achieve:
{'page_order': ['rotatingTest', 'zoomingTest', 'panningTest'],
 'pages': {'panningTest': {'elements': {'7lyuri8g8u5ctwsa' : [{'data': {'created': '04/10/18 12:43',
                                                  'description': 'panning test for posZ',
                                                  'name': 'posePan_positionZ_v001',
                                                  'project': 'TEST',
                                                  'version': '1'},
                                         'name': 'posePan_positionZ_v001',
                                         'thumbnail': '/user_data/posePan_positionZ_v001/posePan_positionZ_v001.thumb.jpg',
                                         'type': 'PosedWidget',
                                         'uid': '7lyuri8g8u5ctwsa'}]}}

Noticed that the '7lyuri8g8u5ctwsa' is missing as part of the key after "elements"

Justin Israel

unread,
Dec 11, 2018, 7:05:33 PM12/11/18
to python_in...@googlegroups.com
What is the reasoning to want  {uid: [element]}  when its always going to be a single item list of the element for that uid key?
 

--
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.
Reply all
Reply to author
Forward
0 new messages