Appending/Merging in Python - python

I have the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
During a for loop new items are added to the list using the extend function. Unfortunately this results in the following structure:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
{
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
The intended result is actually a flat structure such in the following:
[
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"},
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
]
Is it possible to append to the list so that the structure gets built in a flat way.
or
Is it possible to flatten after the loop has finished?

If your list is named l you could use l[0].update(new_dict).
Example:
l = [{u'123456': {'name': "Bill"}}]
l[0].update({u'234567': {'name': "Dave"}})
print(l)
Nice formatted output is:
[
{
u'123456': {'name': 'Bill'},
u'234567': {'name': 'Dave'}
}
]

Where you currently have something like this:
mylist.extend(newdict)
You should use this:
mylist[0].update(newdict)

You can add the items of both dictionaries together:
>>> mylist = [
{
u'123456': {'name': "Bill"},
u'234567': {'name': "Dave"},
u'345678': {'name': "Tom"}
},
]
>>> mydict = {
u'555555': {'name': "Steve"},
u'666666': {'name': "Michael"},
u'777777': {'name': "George"}
}
>>> [dict(mylist[0].items() + mydict.items())]
[{u'123456': {'name': 'Bill'}, u'555555': {'name': 'Steve'}, u'777777': {'name': 'George'}, u'666666': {'name': 'Michael'}, u'345678': {'name': 'Tom'}, u'234567': {'name': 'Dave'}}]
Although it's more clean to just do .update():
>>> mylist[0].update(mydict)

You can use .update(), however this will overwrite values if you'll have duplicated keys.
def flatten(results):
newresult = {}
for subdict : results:
newresult.update(subdict)
return [newresult]

Related

How to loop through a list of dictionary and extract those with the same 'name' and 'school' into a new list while getting their other values in it

I have this list of dictionary and I would like to get those with the same exact value of 'name' and 'school' into a new list and also getting their 'age' merged into a list as well and the rest of the dictionary that is not identical to just add into the list as per usual..
Here is an example of the list of dictionary
[{'name': 'Jane', 'age':12, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'SMU'},{'name': 'Jane', 'age':14, 'school': 'SIT'}, {'name': 'Jane', 'age':16, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'NUS'}]
and I would like it to make it into something like this..
[{'name': 'Jane', 'age': [12,14,16], 'school': 'SIT'}, {'name': 'John', 'age': 13, 'school': 'SMU'}, {'name': 'John', 'age':13, 'school': 'NUS'}]
using Python.. please help!
tried using counter, loops but still can't get it to work..
You could use itertools.groupby().
Example:
import itertools
from pprint import pprint
data = [{'name': 'Jane', 'age':12, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'SMU'},{'name': 'Jane', 'age':14, 'school': 'SIT'}, {'name': 'Jane', 'age':16, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'NUS'}]
keyfunc = lambda x: (x["name"], x["school"])
# needs to be sorted to use groupby
data.sort(key=keyfunc)
output = []
for k,v in itertools.groupby(data, key=keyfunc):
this_group = {
"name": k[0],
"school": k[1],
"age": [i["age"] for i in v],
}
output.append(this_group)
pprint(output)
The output is:
[{'age': [12, 14, 16], 'name': 'Jane', 'school': 'SIT'},
{'age': [13], 'name': 'John', 'school': 'NUS'},
{'age': [13], 'name': 'John', 'school': 'SMU'}]
If you wish to go with the solution based on a buffer dictionary, please check out the dict.setdefault() method.
Example:
buffer = {}
for i in data:
buffer.setdefault((i["name"], i["school"]), []).append(i["age"])
For reference:
https://docs.python.org/3/library/itertools.html#itertools.groupby
https://docs.python.org/3/library/stdtypes.html#dict.setdefault
x = [{'name': 'Jane', 'age':12, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'SMU'},{'name': 'Jane', 'age':14, 'school': 'SIT'}, {'name': 'Jane', 'age':16, 'school': 'SIT'}, {'name': 'John', 'age':13, 'school': 'NUS'}]
new_x = {}
for r in x:
if r['name'] in new_x.keys():
if not isinstance(new_x[r['name']]['age'], list):
new_x[r['name']]['age'] = [new_x[r['name']]['age']]
if r['age'] not in new_x[r['name']]['age']:
new_x[r['name']]['age'].append(r['age'])
else:
new_x[r['name']] = {'age': r['age'], 'school': r['school']}
z = [v.update(name=k) for k, v in new_x.items()]
z = [v for k, v in new_x.items()]
Here is a universal solution to your problem. Only name and school are considered "special". All other keys, like age are converted to list when a new value has to be added.
l = [
{"name": "Jane", "age": 12, "school": "SIT"},
{"name": "John", "age": 13, "school": "SMU"},
{"name": "Jane", "age": 14, "school": "SIT"},
{"name": "Jane", "age": 16, "school": "SIT"},
{"name": "John", "age": 13, "school": "NUS"},
]
r = {}
for x in l:
id = f"{x['name']}-{x['school']}"
if id in r:
for k,v in x.items():
if k not in ["name", "school"]:
if k in r[id]:
if isinstance(r[id][k], list):
r[id][k].append(v)
else:
r[id][k] = [r[id][k], v]
else:
r[id][k] = v
else:
r[id] = x
result = [x for x in r.values()]

Populating a dict with for loop from a list

Hello I have the following list :
Info_Types = [
{'name': 'A'},
{'name': 'B'},
{'name': 'C'}
]
Next, I would like to use this list with a loop in this type of dictionary:
{
"name": Info_Types[i]['name'],
"domainId": "c50d7ff8-0e6d-4132-a528-f286781f017b",
"typeId": "1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1",
"statusId": "00000000-0000-0000-0000-000000005008",
"excludedFromAutoHyperlinking": 'true'
}
The result I want to get is the following:
[{'name': 'A',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'},
{'name': 'B',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'},
{'name': 'C',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'}]
My idea is that I need to use a for loop but I don't really know how to build it. Someone can help me? thanks
It's better to use list comprehension:
result = [
{
"name": name,
"domainId": "c50d7ff8-0e6d-4132-a528-f286781f017b",
"typeId": "1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1",
"statusId": "00000000-0000-0000-0000-000000005008",
"excludedFromAutoHyperlinking": 'true'
}
for name in Info_Types
]

Add dictionary item in list to a dictionary

Hi guys I'm pretty lost with this simple problem. I have a dictionary and a list of dictionaries in python and I want to loop over the list to add each dictionary to the first dictionary but somehow it just adds the last dictionary with the solution I came up with. I'm using Python 3.6.5
This is what I've tried:
res = []
dictionary = {"id": 1, "name": "Jhon"}
dictionary_2 = [
{"surname": "Doe", "email": "jd#example.com"},
{"surname": "Morrison", "email": "jm#example.com"},
{"surname": "Targetson", "email": "jt#example.com"}
]
for info in dictionary_2:
aux_dict = dictionary
aux_dict["extra"] = info
res.append(aux_dict)
print(res)
What I expect is:
[{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Doe', 'email': 'jd#example.com'}},
{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Morrison', 'email': 'jm#example.com'}},
{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Targetson', 'email': 'jt#example.com'}}]
And this is what I get
[{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Targetson', 'email': 'jt#example.com'}},
{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Targetson', 'email': 'jt#example.com'}},
{'id': 1, 'name': 'Jhon', 'extra': {'surname': 'Targetson', 'email': 'jt#example.com'}}]
This is probably a duplicate of some other question but I can't manage to find it
This is because you keep adding the same aux_dict to res.
What you probably want to do is make a copy of dictionary; just assigning it to aux_dict does not make a copy.
This is how you make a (shallow) copy:
aux_dict = dictionary.copy()
That would be sufficient in your case.
You can achieve this in one line using list comprehension and dict constructor:
dictionary = {"id": 1, "name": "Jhon"}
dictionary_2 = [
{"surname": "Doe", "email": "jd#example.com"},
{"surname": "Morrison", "email": "jm#example.com"},
{"surname": "Targetson", "email": "jt#example.com"}
]
# ...
res = [dict(dictionary, extra=item) for item in dictionary_2]
# ...
print(res)

Python - merge nested dictionaries

I have this data structure:
playlists_user1={'user1':[
{'playlist1':{
'tracks': [
{'name': 'Karma Police','artist': 'Radiohead', 'count': 1.0},
{'name': 'Bitter Sweet Symphony','artist': 'The Verve','count': 2.0}
]
}
},
{'playlist2':{
'tracks': [
{'name': 'We Will Rock You','artist': 'Queen', 'count': 3.0},
{'name': 'Roxanne','artist': 'Police','count': 5.0}
]
}
},
]
}
playlists_user2={'user2':[
{'playlist1':{
'tracks': [
{'name': 'Karma Police','artist': 'Radiohead', 'count': 2.0},
{'name': 'Sonnet','artist': 'The Verve','count': 4.0}
]
}
},
{'playlist2':{
'tracks': [
{'name': 'We Are The Champions','artist': 'Queen', 'count': 4.0},
{'name': 'Bitter Sweet Symphony','artist': 'The Verve','count': 1.0}
]
}
},
]
}
I would like to merge the two nested dictionaries into one single data structure, whose first item would be a playlist key, like so:
{'playlist1': {'tracks': [{'count': 1.0, 'name': 'Karma Police', 'artist': 'Radiohead'}, {'count': 2.0, 'name': 'Bitter Sweet Symphony', 'artist': 'The Verve'}]}}
I have tried:
prefs1 = playlists_user1['user1'][0]
prefs2 = playlists_user2['user2'][0]
prefs3 = prefs1.update(prefs2)
to no avail.
how do I solve this?
Since your playlist values are already a list of lists of dictionaries with one key (a bit obfuscated if you ask me):
combined = {}
for playlist in playlists_user1.values()[0]:
combined.update(playlist)
for playlist in playlists_user2.values()[0]:
combined.update(playlist)
or if you have many of these, make a list and:
combined = {}
for playlistlist in user_playlists:
for playlist in playlistlist.values()[0]:
combined.update(playlist)

pystache: render context inside lambda

This is very similar to https://github.com/defunkt/pystache/issues/157, however in the mentioned post didn't really answer...
My target: print the following lines:
Al,John,Jack
Tim,Tom,Todd
without a final comma.
I tried this way:
ctx = {
'gangs': [
{'gangsters': [ {'name': 'Al' }, {'name': 'John'}, {'name': 'Jack'}]},
{'gangsters': [ {'name': 'Tim'}, {'name': 'Tom'} , {'name': 'Todd'}]},
]
}
class Lambdas(object):
def __init__(self, renderer):
self.renderer = renderer
def rstrip(self):
"Remove last character"
print self.renderer.context
return lambda s: self.renderer.render(s, self.renderer.context)[:-1]
renderer = pystache.Renderer(missing_tags='strict')
print renderer.render("""
{{#gangs}}
{{#rstrip}}{{#gangsters}}{{name}},{{/gangsters}}{{/rstrip}}
{{/gangs}}
""", ctx, Lambdas(renderer))
The output:
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
Al,John,Jack
Al,John,Jack
The culprit is the invocation to render() inside rstrip. Notice how, during the second call, the 3d element of the ContextStack is exactly identical to the previous call.
Is this a bug, or am I missing something?!?
Answered upstream: https://github.com/defunkt/pystache/issues/158
def rstrip(self):
"Remove last character"
return lambda s: copy.deepcopy(self.renderer).render(s, self.renderer.context)[:-1]

Categories

Resources