Django: replace columns in ValueQuerySet - python

My django project database is organized like this:
Student.objects.values('name', 'schoolId') = [ {'name': 'Bob', 'schoolId': 5},
{'name': 'Alice', 'schoolId': 2} ]
School.objects.values('schoolId', 'name') = [ {'schoolId': 2, 'name': 'East High'},
{'schoolId': 5, 'name': 'West High'} ]
I want to generate a something like this:
foo = [ {'name': 'Bob', 'school': 'West High'},
{'name': 'Alice', 'school': 'East High'} ]
Basically it iterates through the first ValueQuerySet to replace all ('schoolId', int) pairs with ('school', schoolNameStr). Logically it can achieve this by searching the schoolId value in School table and returning the corresponding name attribute of each entry.
I know and can use a for loop and filter to do this. But how can I implement it any faster?

Related

Getting Value Passing a Key From a List of Lists

I am given a list of lists, similar to the following. I am very new to Python
[
{'id': 1244},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'},
]
[
{'id': 1245},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'},
]
[
{'id': 1246},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'},
]
How can I get the "name" value from this, without having to nest loops?
My current code is:
for _row in _rs:
print(_row)
print(_row["name])
However, I am receiving an error message: TypeError: list indices must be integers, not str
So, how can I accomplish this?
if it trully a list of list there is a comma between each list. then you can easily do that:
for i in x:
print(i[1]['name'])
How does this look?
l = [{'id': 1244}, {'name': 'example.com'}, ...]
names = e['name'] for e in l if 'name' in e]
print(names)
>>> ['example.com']
You can move around the list and check if each dictionary has the "name" key, and print the result if yes.
list1 = [{'id': 1244},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'}]
for dictionary in list1:
if "name" in dictionary.keys(): # Whether the dictionary looks like {"name": ...}
print(dictionary["name"])
break # Exit the loop now that we have the name, instead of going through the whole list.
Edit: your input is broken. Before being able to work on it, you want to change the function that gives you what you showed in the OP into that:
[ # <-- outer list starts
[
{'id': 1244},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain- overview.htm'},
{'monitoring_text_string': 'quality product'},
], # <--
[
{'id': 1245},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'},
], # <--
[
{'id': 1246},
{'name': 'example.com'},
{'monitoring_enabled': 'Yes'},
{'monitoring_url': 'http://www.example.com/'},
{'monitoring_page_url': 'http://www.example.com/products-spool-chain-overview.htm'},
{'monitoring_text_string': 'quality product'},
]
] # <-- outer list ends
Even better:
lists_of_dicts = [
[{'id': 1244,
'name': 'example.com',
'monitoring_enabled': 'Yes',
'monitoring_url': 'http://www.example.com/',
'monitoring_page_url': 'http://www.example.com/products-spool-chain- overview.htm',
'monitoring_text_string': 'quality product'}],
[{'id': 1245,
'name': 'example.com',
'monitoring_enabled': 'Yes',
'monitoring_url': 'http://www.example.com/',
'monitoring_page_url': 'http://www.example.com/products-spool-chain- overview.htm',
'monitoring_text_string': 'quality product'}],
[{'id': 1246,
'name': 'example.com',
'monitoring_enabled': 'Yes',
'monitoring_url': 'http://www.example.com/',
'monitoring_page_url': 'http://www.example.com/products-spool-chain- overview.htm',
'monitoring_text_string': 'quality product'}]
]

How to count how many times a specific value in a dictionary of dictionaries in Python 3

I know there must be a very simple solution to this question but I am new with Python and cannot figure out how to do it.
All I simply want to do is count how many times a particular value appears in this dictionary, for example, how many males there are.
people = {}
people['Applicant1'] = {'Name': 'David Brown',
'Gender': 'Male',
'Occupation': 'Office Manager',
'Age': '33'}
people['Applicant2'] = {'Name': 'Peter Parker',
'Gender': 'Male',
'Occupation': 'Postman',
'Age': '25'}
people['Applicant3'] = {'Name': 'Patricia M',
'Gender': 'Female',
'Occupation': 'Teacher',
'Age': '35'}
people['Applicant4'] = {'Name': 'Mark Smith',
'Gender': 'Male',
'Occupation': 'Unemployed',
'Age': '26'}
Any help is much appreciated!
For your example, you have applicants and their data. The data you are checking is their gender, so the below code will accomplish that.
amount = 0 # amount of people matching condition
for applicant in people.values(): # looping through all applicants
if applicant.get('Gender', False) == 'Male': # checks if applicant['Gender'] is 'Male'
# note it will return False if ['Gender'] wasn't set
amount += 1 # adds matching people to amount
This will get the amount of males in the applicant list.
I'd suggest refactoring your logic a bit to use a list of dicts.
people = [
{
'Name': 'David Brown',
'Gender': 'Male',
'Occupation': 'Office Manager',
'Age': '33'
},
{
'Name': 'Peter Parker',
'Gender': 'Male',
'Occupation': 'Postman',
'Age': '25'
},
{
'Name': 'Patricia M',
'Gender': 'Female',
'Occupation': 'Teacher',
'Age': '35'
},
{
'Name': 'Mark Smith',
'Gender': 'Male',
'Occupation': 'Unemployed',
'Age': '26'
}
]
Then you can use logic like
[applicant for applicant in people if applicant['Gender'] == 'Male']
Which will give you all of the males in the list
This is a function to count the number of occurrences of a given value inside a dictionary:
def count(dic, val):
sum = 0
for key,value in dic.items():
if value == val:
sum += 1
if type(value) is dict:
sum += count(dic[key], val)
return sum
Then you can use it as follow:
result = count(people, 'Male')

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)

Using PyMongo insert_many and empty/null values

I'm in the process of populating a mongoDB database and and not sure what to do with null values when using the insert_many statement (I should state at this point that I'm new to both Python and MongoDB)
The data I am inserting is two dimensional traditional SQL like data obtained from a text file, it looks something like this:
emp = [
[7839, 'KING', 'PRESIDENT', null],
[7698, 'BLAKE', 'MANAGER', 7839],
[7782, 'CLARK', 'MANAGER', 7839],
[7566, 'JONES', 'MANAGER', 7839],
[7788, 'SCOTT', 'ANALYST', 7566],
[7902, 'FORD', 'ANALYST', 7566],
[7369, 'SMITH', 'CLERK', 7902],
[7499, 'ALLEN', 'SALESMAN', 7698],
[7521, 'WARD', 'SALESMAN', 7698],
[7654, 'MARTIN', 'SALESMAN', 7698],
[7844, 'TURNER', 'SALESMAN', 7698],
[7876, 'ADAMS', 'CLERK', 7788],
[7900, 'JAMES', 'CLERK', 7698],
[7934, 'MILLER', 'CLERK', 778]
]
And my database population looks like this
employee.insert_many([{
"_id" : emp[i,0],
"Name": emp[i,1],
"Role": emp[i,2],
"Boss": emp[i,3]
}
for i in range(len(emp))
],False)
Ideally I would like "KING", the president, to not have the "Boss" field but I'm not sure how to achieve this. Could anyone point me in the right direction?

Python Dictionaries: Grouping Key, Value pairs based on a common key, value

I have a list that contains dictionaries like this:
list1 = [{'name': 'bob', 'email': 'bob#bob.com', 'address': '123 house lane',
'student_id': 12345}, {'name': 'steve', 'email': 'steve#steve.com',
'address': '456 house lane', 'student_id': 34567}, {'name': 'bob',
'email': 'bob2#bob2.com', 'address': '789 house lane', 'student_id': 45678}]
Is there a way in python to group selected key, values pairs within a new dictionary based on 'name' value? For instance, something like this as an end result:
new_list = [
{'name': 'bob',
{'emails': ['bob#bob.com',
'bob2#bob2.com']},
{'address': ['123 house lane',
'789 house lane']},
{'name': 'steve',
{'email': ... },
{'address': ... }}
# let's assume the list1 has various entries at some point
# which may or may not have duplicate 'name' values
# and new_list will hold the groupings
]
Sounds like this is what you want to do:
list1 = [{'name': 'bob', 'email': 'bob#bob.com',
'address': '123 house lane', 'student_id': 12345},
{'name': 'steve', 'email': 'steve#steve.com',
'address': '456 house lane', 'student_id': 34567},
{'name': 'bob', 'email': 'bob2#bob2.com',
'address': '789 house lane', 'student_id': 45678}]
import operator
list1.sort(key=operator.itemgetter('name'))
new_list = []
for studentname, dicts in itertools.groupby(list1, operator.itemgetter('name')):
d = {'name': studentname}
for dct in dicts:
for key,value in dct.items():
if key == 'name':
continue
d.setdefault(key, []).append(value)
new_list.append(d)
DEMO:
[{'address': ['123 house lane', '789 house lane'],
'email': ['bob#bob.com', 'bob2#bob2.com'],
'name': 'bob',
'student_id': [12345, 45678]},
{'address': ['456 house lane'],
'email': ['steve#steve.com'],
'name': 'steve',
'student_id': [34567]}]
If you were going to use this extensively you should probably hard-code some better names (addresses instead of address for instance) and make a mapping that populates them for you.
keys_mapping = {'address': 'addresses',
'email': 'emails',
'student_id': 'student_ids'}
for studentname, dicts in itertools.groupby(list1, operator.itemgetter('name')):
d = {'name': studentname}
for dct in dicts:
for key,value in dct_items():
new_key = keys_mapping.get(key,key)
# get the updated value if it's defined, else give `key`
d.setdefault(new_key, []).append(value)
new_list.append(d)
The code below gives you nested dictionaries. Nested dictionaries give you faster processing to find the key while in list you have to create a loop.
list1 = [{'name': 'bob', 'email': 'bob#bob.com', 'address': '123 house lane',
'student_id': 12345}, {'name': 'steve', 'email': 'steve#steve.com',
'address': '456 house lane', 'student_id': 34567}, {'name': 'bob',
'email': 'bob2#bob2.com', 'address': '789 house lane', 'student_id': 45678}]
dict1 = {}
for content in list1:
if content['name'] in [name for name in dict1]:
dict1[content['name']] = {'emails': dict1[content['name']]['emails'] + [content['address']], 'addresses': dict1[content['name']]['addresses'] + [content['email']]}
else:
dict1[content['name']] = {'emails': [content['email']], 'addresses': [content['address']]}
print dict1
Output of the code is
{'steve': {'emails': ['steve#steve.com'], 'addresses': ['456 house lane']}, 'bob': {'emails': ['bob#bob.com', '789 house lane'], 'addresses': ['123 house lane', 'bob2#bob2.com']}}

Categories

Resources