简体   繁体   中英

splitting nested dictionary based on a key values

Would anyone be able to give me a tip on how to split a nested dictionary into separate nested dictionaries based on a common key name called score and the value of score ?

For example break up this nested dictionary nested_group_map_original :

nested_group_map_original = {
    'group_l1n': {'score': 0.12949562072753906, 'VMA-1-1': '14', 'VMA-1-2': '13', 'VMA-1-3': '15', 'VMA-1-4': '11', 'VMA-1-5': '9', 'VMA-1-7': '7', 'VMA-1-10': '21', 'VMA-1-11': '16'}, 
    'group_l1s': {'score': -0.40303707122802734, 'VMA-1-6': '8', 'VMA-1-8': '6', 'VMA-1-9': '10', 'VMA-1-12': '19', 'VMA-1-13': '20', 'VMA-1-14': '37', 'VMA-1-15': '38', 'VMA-1-16': '39'}, 
    'group_l2n': {'score': 0.6091512680053768, 'VAV-2-1': '12032', 'VAV-2-2': '12033', 'VMA-2-3': '31', 'VMA-2-4': '29', 'VAV-2-5': '12028', 'VMA-2-6': '27', 'VMA-2-7': '30', 'VMA-2-12': '26'}, 
    'group_l2s': {'score': 0.11078681945799929, 'VMA-2-8': '34', 'VAV-2-9': '12035', 'VMA-2-10': '36', 'VMA-2-11': '25', 'VMA-2-13': '23', 'VMA-2-14': '24'}
               }

Make it look like this below but in a programmatic way for two separate nested dictionaries named nested_group_map_copy_lows and nested_group_map_copy_high :

nested_group_map_copy_lows = {
    'group_l1s': {'score': -0.40303707122802734, 'VMA-1-6': '8', 'VMA-1-8': '6', 'VMA-1-9': '10', 'VMA-1-12': '19', 'VMA-1-13': '20', 'VMA-1-14': '37', 'VMA-1-15': '38', 'VMA-1-16': '39'}, 
    'group_l2s': {'score': 0.11078681945799929, 'VMA-2-8': '34', 'VAV-2-9': '12035', 'VMA-2-10': '36', 'VMA-2-11': '25', 'VMA-2-13': '23', 'VMA-2-14': '24'}
                   }

nested_group_map_copy_highs = {
    'group_l2n': {'score': 0.6091512680053768, 'VAV-2-1': '12032', 'VAV-2-2': '12033', 'VMA-2-3': '31', 'VMA-2-4': '29', 'VAV-2-5': '12028', 'VMA-2-6': '27', 'VMA-2-7': '30', 'VMA-2-12': '26'},
    'group_l1n': {'score': 0.12949562072753906, 'VMA-1-1': '14', 'VMA-1-2': '13', 'VMA-1-3': '15', 'VMA-1-4': '11', 'VMA-1-5': '9', 'VMA-1-7': '7', 'VMA-1-10': '21', 'VMA-1-11': '16'},     
                   }

Not really sure how to tackle this, I think I need to use enumerate to create entire new dictionaries but if I try to find highest scores in a separate list scores_

scores_ = []
for i in nested_group_map_original:
    scores_.append(nested_group_map_original[i]["score"])
    
scores_sorted = sorted(scores_, key = float)

Then slice for highest and lowest values:

scores_sorted_highs = scores_sorted[2:]
scores_sorted_lows = scores_sorted[:2]

I am stuck here I dont think del is way to go, any tips greatly appreciated... I know in my code I am not even defining new dictionaries which I think I could do with Python enumerate but not sure how to implement that

for i in nested_group_map_original:
    if nested_group_map_original[i]["score"] in scores_sorted_highs:
        del nested_group_map_original[i]

This errors out:

RuntimeError: dictionary changed size during iteration

You can sort the keys of the original dictionary according to their corresponding scores, like so:

sorted_keys = sorted(nested_group_map_original, key = lambda x: nested_group_map_original[x]['score'])

You can then split into two different dictionaries according to how many values you want in each. Like in your example of two, you could do the following:

scores_sorted_lows = {k:nested_group_map_original[k] for k in sorted_keys[:2]}
scores_sorted_highs = {k:nested_group_map_original[k] for k in sorted_keys[2:]}

If the dict isn't super huge, then one easy way to do this would just be to construct the list by filtering the map twice using a comprehension:

nested_group_map_low = {k:v for k,v in nested_group_map_original.items() if is_low_score(v["score"])}
nested_group_map_high = {k:v for k,v in nested_group_map_original.items() if not is_low_score(v["score"])}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM