Skip to content Skip to sidebar Skip to footer

Change One Dict/list Python Structure To Another

I have the following data data={ None: [ {'ne': '1', 'na': '1'}, {'ne': '2', 'na': '2'}, {'ne': '3', 'na': '3'},

Solution 1:

new = [x forkey,value in data.items() forxin value]

# remove duplicate dictionaries
new = [dict(t) fortin {tuple(d.items()) fordin new}]

fordin new:
    d['country'] = [key forkey,data in data.items() if d in data]

print(new)

>>> [{'ne': '2', 'na': '2', 'country': [None, 'AO']}, 
     {'ne': '4', 'na': '4', 'country': [None]}, 
     {'ne': '1', 'na': '1', 'country': [None, 'NZ']}, 
     {'ne': '6', 'na': '6', 'country': ['AO']}, 
     {'ne': '3', 'na': '3', 'country': [None]}]

If you want to preserve the order

new = [x for n,(key,value) inenumerate(data.items()) for x in value]

seen = set()
new_l = []
for d in new:
    t = tuple(d.items())
    if t notin seen:
        seen.add(t)
        new_l.append(d)

for d in new_l:
    d['country'] = [key for key,data in data.items() if d in data]

print(new_l)

>>> [{'ne': '1', 'na': '1', 'country': [None, 'NZ']}, 
     {'ne': '2', 'na': '2', 'country': [None, 'AO']}, 
     {'ne': '3', 'na': '3', 'country': [None]}, 
     {'ne': '4', 'na': '4', 'country': [None]}, 
     {'ne': '6', 'na': '6', 'country': ['AO']}]

Solution 2:

This is a really naive approach to solve your problem, due to it requiring that the inner dictionaries are sorted in the same order for it to "match" earlier found dictionaries.

For more complex dictionaries inside of the country this might not give correct results:

data={
       None: [
               {'ne': '1', 'na': '1'},
               {'ne': '2', 'na': '2'},
               {'ne': '3', 'na': '3'},
               {'ne': '4', 'na': '4'}
             ],
      'AO': [
               {'ne': '2', 'na': '2'},
               {'ne': '6', 'na': '6'}
            ],
      'NZ': [
               {'ne': '1', 'na': '1'}
            ]
      }

d = {}
for country in data:
    for dictionary in data[country]:
        # Create a key that is a string of the dictionary, and value is dictionary plus country
        x = d.setdefault(str(dictionary), dictionary | {"country": []})
        # If you're using Python < 3.9, use this instead:# x = d.setdefault(str(dictionary), {**dictionary, "country": []})
        x["country"].append(country)

# pprint only used to represent data betterimport pprint
pprint.pp(list(d.values()))

Output:

[{'ne': '1', 'na': '1', 'country': [None, 'NZ']},
 {'ne': '2', 'na': '2', 'country': [None, 'AO']},
 {'ne': '3', 'na': '3', 'country': [None]},
 {'ne': '4', 'na': '4', 'country': [None]},
 {'ne': '6', 'na': '6', 'country': ['AO']}]

Solution 3:

Firstly, I'm assuming ne and na are always the same.

An optimal intermediate data structure is a dict with ne/na as keys and country lists as values:

{'1': [None, 'NZ'],
 '2': [None, 'AO'],
 '3': [None],
 '4': [None],
 '6': ['AO']}

Once you have that goal in mind, it's super simple to do it Pythonically:

inter = {}
fork, dicts in data.items():
    fordin dicts:
        inter.setdefault(d['ne'], []).append(k)
  • dict.setdefault() is used to get the value if it exists, or if not, set it to a default, which is an empty list here. It's functionally the same as this:
    ne = d['ne']
    ifnenot in inter:
        inter[ne] = []
    inter[ne].append(k)
    
    You could also use collections.defaultdict(list) to do the same thing even more easily.

And once you have that dict, you just need to unpack it into a list of dicts:

result = [{'ne': ne, 'na': ne, 'country': c} forne, c in inter.items()]

Which becomes:

[{'ne': '1', 'na': '1', 'country': [None, 'NZ']},
 {'ne': '2', 'na': '2', 'country': [None, 'AO']},
 {'ne': '3', 'na': '3', 'country': [None]},
 {'ne': '4', 'na': '4', 'country': [None]},
 {'ne': '6', 'na': '6', 'country': ['AO']}]

Post a Comment for "Change One Dict/list Python Structure To Another"