1

I have the following structure:

input = {
'clark': {
          'elements':['id[3]_element[1]','id[3]_element[2]','id[3]_element[3]'],
          'nickname': 'superman',
          'registered': 'Y'
         },
'rodger': {
          'elements':['id[2]_element[1]','id[2]_element[2]','id[2]_element[3]'],
          'nickname': 'rodjeuur',
          'registered': 'N'
         },
'ratman': {
          'elements':['id[6]_element[1]','id[6]_element[2]','id[6]_element[3]'],
          'nickname': 'rat',
          'registered': 'Y'
         },
'marylin': {
          'elements':['id[90]_element[1]','id[90]_element[2]','id[90]_element[3]'],
          'nickname': 'monroe',
          'registered': 'Y'
         },
'snoopy': {
          'elements':['id[1]_element[1]','id[1]_element[2]','id[1]_element[3]'],
          'nickname': 'lame',
          'registered': 'N'
         },
'dummy_field[1]': 'dogfood',
'dummy_field[2]': 'monkeyjump',
'id[3]_element[1]':{
    'feature': 'vision glass',
    'value': 0.12,
    'color': 'blue'
},
'id[3]_element[2]':{
    'feature': 'height',
    'value': 1.88
},
'id[3]_element[3]':{
    'feature': 'cookingskill',
    'value': 0
},
'id[6]_element[1]':{
    'feature': 'rat teeth',
    'value': 25,
    'similarity':'luis suarez'
},
'id[6]_element[2]':{
    'feature': 'height',
    'value': 1.70
},
'id[6]_element[3]':{
    'feature': 'cookingskill',
    'value': 0.5
},
'id[2]_element[1]':{
    'feature': 'tennis raquet',
    'value': 500000,
    'particularity':'second arm'
},
'id[2]_element[2]':{
    'feature': 'height',
    'value': 1.78
},
'id[2]_element[3]':{
    'feature': 'trickshot',
    'value': 120
},
'id[1]_element[1]':{
    'feature': 'mood',
    'value': 0,
    'particularity':'depressed'
},
'id[1]_element[2]':{
    'feature': 'height',
    'value': 0.45
},
'id[1]_element[3]':{
    'feature': 'sadness',
    'value': 10000000
},
'id[90]_element[1]':{
    'feature': 'charm',
    'value': 500000
},
'id[90]_element[2]':{
    'feature': 'height',
    'value': 1.72
},
'id[90]_element[3]':{
    'feature': 'cookingskills',
    'value': 0
}
}

And a list over which to iterate:

lnames=['clark','ratman','snoopy','marylin']

I would like to obtain the following list of dictionnaries as result:

output=[{'vision glass':0.12, 'height':1.88, 'cookingskill':0},
    {'rat teeth':25, 'height':1.70, 'cookingskill':0.5},
    {'mood':0, 'height':0.45, 'sadness':10000000},
    {'charm':500000, 'height':1.72, 'cookingskills':0}
]

I started the very basic code:

output=[{.... for el in input[name]['elements']} for name in lnames]

I can reach each name elements and iterate over them to access the different 'features' and 'values', but I do not know how to group them into dictionnaries for a given name.

Do anyone has an idea?

EDIT

Now supposing I have the same input except there is an '@' in the field 'elements' of each name:

input = {
'clark': {
          'elements':['@id[3]_element[1]','@id[3]_element[2]','@id[3]_element[3]'],
          'nickname': 'superman',
          'registered': 'Y'
         },
'rodger': {
          'elements':['@id[2]_element[1]','@id[2]_element[2]','@id[2]_element[3]'],
          'nickname': 'rodjeuur',
          'registered': 'N'
         },
'ratman': {
          'elements':['@id[6]_element[1]','@id[6]_element[2]','@id[6]_element[3]'],
          'nickname': 'rat',
          'registered': 'Y'
         },
'marylin': {
          'elements':['@id[90]_element[1]','@id[90]_element[2]','@id[90]_element[3]'],
          'nickname': 'monroe',
          'registered': 'Y'
         },
'snoopy': {
          'elements':['@id[1]_element[1]','@id[1]_element[2]','@id[1]_element[3]'],
          'nickname': 'lame',
          'registered': 'N'
         },
'dummy_field[1]': 'dogfood',
'dummy_field[2]': 'monkeyjump',
'id[3]_element[1]':{
    'feature': 'vision glass',
    'value': 0.12,
    'color': 'blue'
},
'id[3]_element[2]':{
    'feature': 'height',
    'value': 1.88
},
'id[3]_element[3]':{
    'feature': 'cookingskill',
    'value': 0
},
'id[6]_element[1]':{
    'feature': 'rat teeth',
    'value': 25,
    'similarity':'luis suarez'
},
'id[6]_element[2]':{
    'feature': 'height',
    'value': 1.70
},
'id[6]_element[3]':{
    'feature': 'cookingskill',
    'value': 0.5
},
'id[2]_element[1]':{
    'feature': 'tennis raquet',
    'value': 500000,
    'particularity':'second arm'
},
'id[2]_element[2]':{
    'feature': 'height',
    'value': 1.78
},
'id[2]_element[3]':{
    'feature': 'trickshot',
    'value': 120
},
'id[1]_element[1]':{
    'feature': 'mood',
    'value': 0,
    'particularity':'depressed'
},
'id[1]_element[2]':{
    'feature': 'height',
    'value': 0.45
},
'id[1]_element[3]':{
    'feature': 'sadness',
    'value': 10000000
},
'id[90]_element[1]':{
    'feature': 'charm',
    'value': 500000
},
'id[90]_element[2]':{
    'feature': 'height',
    'value': 1.72
},
'id[90]_element[3]':{
    'feature': 'cookingskills',
    'value': 0
}
}

Using the folowing code:

import re

def at(x):
    return input[re.sub(r'@','',x)] 

I believed I could proceed with dictionary comprehension like this:

output=[{at(el)['feature']:at(el)['value'] for el in input[name]['elements']} for name in lnames]

But I got the error NameError: global name 'at' is not defined. When I use list comprehension instead of dictionary comprehension, it works , but:

1 - I still wonder what this name error means since it is linked to dictionary comprehension. 2 - this is not the expected result.

The edit is not so complex compared to the initial answer, but points 1/ really annoys me!

3 Answers 3

3

You were almost there. It should be:

output=[{input[el]['feature']:input[el]['value']
  for el in input[name]['elements']} for name in lnames]
Sign up to request clarification or add additional context in comments.

3 Comments

Thnaks, this answer perfectly the first question but I unfortunately had to add an edit!
I have no problem generating the list of dictionaries with your edited code. Where are you declaring at()? By the way, there is no need to use regex for such a simple replacement. You could just use return input[x.replace('@', '')]
I declare it just before the instruction output=[{at(el)['feature']:at(el)['value'] for el in input[name]['elements']} for name in lnames] . I am using python 2.7
1

A comprehensive solution with existence checks

output = [
    {
        input[element]['feature'] : input[element]['value']
        for element in input.get(name,{}).get('elements',[])
    }
    for name in lnames
]

Comments

0

It sometimes helps to write out regular loops, then convert to a list comprehension. After doing so, I got the following code:

output = [{input[element]['feature']: input[element]['value'] 
           for element in input[name]['elements']}
          for name in lnames]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.