How to create an 'contact book' in python using dictionaries? - python

I'm trying to create an contact book indexed by 'nickname' that allows the user to save a persons name, address and number. But I don't quite understand how to do it using dictionaries, if I had it my way I would just use a list.
e.g
myList = [["Tom","1 Fairylane", "911"],["Bob","2 Fairylane", "0800838383"]]
And then if I wanted to see a certain contact I would just use some more code to search for a pattern. But I just can't figure out how to do it with a dictionary

You can start with this:
my_dict = {"Tom": {"name": "Tom Jones", "address": "1 Fairylane", "phone": "911"},
"Bob": {"name": "Bob Marley", "address": "2 Fairylane", "phone": "0800838383"}
}
then you can simply access records using
my_dict["Tom"]["name"]
or
my_dict["Bob"]["phone"]

Keys in a dictionary a unique. So if you have a list of contacts with no name twice you can use code like this:
contacts = {}
contacts['Tom'] = ["1 Fairylane", 911]
contacts['Bob'] = ["2 Fairylane", 0800838383]
so adding data to a dictionary is based on the access operator [].
If you want to initialize a dictionary with ready data, use code like this:
contacts = {'Tom' : ["1 Fairylane", 911],
'Bob' : ["2 Fairylane", 0800838383]}
access to a certain contact works like this:
print(contacts['Tom'])
Note, if you've got a second, say "Tom", this wouldn't work. You'd have to add date of birth or lastname or whatever to make it unique

As mentioned by DomTomCat you could set the dictionary key to be the first name, and the data then contained in a list. One thing to note is that dictionaries are unsorted. So whilst they provide a very fast search (they are essentially a hash table) for a key it will require you to do a bit of work if you wish to display sorted subsets of results.

Related

How to extract the given keys in one dictionary from another into a new dictionary (Python)

I'm trying to practice sets and dictionaries, and one thing I've been finding is myself stuck on this practice problem over and over.
For example if I have a dictionary like
employees =[
{
"name": "Jamie Mitchell",
"job": "Head Chef",
"city": "Toronto",
},
{
"name": "Michell Anderson",
"job": "Line Cook",
"city": "Mississauga",
}
]
How would I extract the second part of the dictionary from the first in order to only have the information on the right be in a new dictionary?
Quick Answer:
employees is a list of dictionaries so you can just directly index the list to get Michell:
newDict = employees[1]
More Detailed Answer:
Firstly, here is how you create a key-value pair in a dictionary:
dct = {}
dct['color'] = 'blue' # dct = {'color':'blue'}
Knowing this, all you would need to copy a dictionary is the keys and values. You can use the .keys(),.values(), and .items() methods of dictionaries to do this.
dct.keys() # returns a list of all the keys -> ['color']
dct.values() # returns a list of all the values -> ['blue']
dct.items() # return a list of all the pairs as tuples -> [('color','blue')]
There are other options to copy as another user has mentioned however I strongly suggest you get used to work with the 3 methods listed above. If you haven't already, make sure you are really comfortable with lists before you jump into dictionaries and combined structures. You already seem to know how to work loops so hopefully this is helpful enough, good luck!
You have them backwards; the outer one [] is a list. The inner ones {} are dictionaries.
You can get the second one with employees[1] (indexing starts from 0) or the last one with employees[-1] (in this case they are the same).
If you need a copy, you can call .copy() on the result:
second_employee = employees[1]
copied_details = second_employee.copy()

How do I give the list an index name?

I've seen something like this construction somewhere:
list.append({
'title': scName,
'link': scLink,
})
print('Names:', list['title'])
print('Links:', list['link'])
Can you please show a working example?
Here, the dict is being appended to a list. And to use inner data, we've to put list[<index_of_inner_dict>][key_of_that_data]. In short, we've to go to the whole inner data index, then the index of required value. Here we have only one dict, it is simply list[0]. Also, scName and scLink are not defined, I'm assuming that they are simple strings. Your code:
l=[]
l.append({
'title': "scName",
'link': "scLink"
})
print (l)
print('Names:', l[0]['title'])
print('Links:', l[0]['link'])
What I believe you are asking is for someone to give you an example of how to use a dictionary. To give some background on dictionaries, they store information in key-value pairs. The key, which is the "index name" you mentioned in your title is mapped to a value stored. You can read here if you are still confused.
For the code example you gave, what it looks like you are attempting to do is add multiple dictionaries to a list and then access those values. Here is an example.
lst_of_employees = []
lst_of_employees.append({"name": "John", "salary": "10000"})
lst_of_employees.append({"name": "Jane", "salary": "20000"})
for emp in lst_of_employees:
print(f"{emp['name']} makes ${emp['salary']} a year.")
You can make the value of the key-value pair whatever you would like. Here is an example with the value stored at the key "salary" as another dictionary.
lst_of_employees = []
lst_of_employees.append({"name": "John", "salary": {"base": 8000, "bonus": 2000}})
lst_of_employees.append({"name": "Jane", "salary": {"base": 15000, "bonus": 5000}})
for emp in lst_of_employees:
employee = emp["name"]
base = emp["salary"]["base"]
bonus = emp["salary"]["bonus"]
print(f"{emp['name']} makes ${base+bonus} a year.")

Operate on dicts nested inside a list using a list comprehension

I have a list of dicts, each dict has a data key. Each data key contains a bunch of attributes about a person, none of those attributes are mandatory:
persons = [
{"Name": "John", "data": {"Age": 23, "Gender": "Male"}},
{"Name": "Jane", "data": {"Age": 22, "Gender": "Female"}},
{"Name": "Harry", "data": {"Age": 22}},
{"Name": "Hermione", "data": {"Gender": "Female"}},
]
What I'd like to do is extract a distinct list of the Age values. I've done it like this:
ages = set()
persondatas = [person['data'] for person in persons]
for persondata in persondatas:
if 'Age' in persondata:
ages.add(persondata['Age'])
ages
which returns:
{22, 23}
which is exactly what I want but I'm thinking there must be a better, neater, way than looping over a list that I obtained using a list comprehension. Can I do the required work inside a list comprehension perhaps? My first aborted attempt went like this:
[person['data']['Age'] for person in l]
which failed:
KeyError: 'Age'
There must be a better way but I've fiddled around and can't work it out. Can anyone help?
You could add a conditional into your list comprehension - knock out both operations with one loop.
>>> {person['data']['Age'] for person in persons if 'Age' in person['data']}
set([22, 23])
Notice how I use curly braces ({}), instead of square brackets ([]), to denote a set comprehension.
Try this:
ages = set([person["data"]["Age"] for person in persons if "Age" in person["data"]])
One solution is a list comprehension combined with filter.
set(filter(None, [p['data'].get('Age') for p in persons]))

How to query for distinct results in mongodb with python?

I have a mongo collection with multiple documents, suppose the following (assume Tom had two teachers for History in 2012 for whatever reason)
{
"name" : "Tom"
"year" : 2012
"class" : "History"
"Teacher" : "Forester"
}
{
"name" : "Tom"
"year" : 2011
"class" : "Math"
"Teacher" : "Sumpra"
}
{
"name" : "Tom",
"year" : 2012,
"class" : "History",
"Teacher" : "Reiser"
}
I want to be able to query for all the distinct classes "Tom" has ever had, even though Tom has had multiple "History" classes with multiple teachers, I just want the query to get the minimal number of documents such that Tom is in all of them, and "History" shows up one time, as opposed to having a query result that contains multiple documents with "History" repeated.
I took a look at:
http://mongoengine-odm.readthedocs.org/en/latest/guide/querying.html
and want to be able to try something like:
student_users = Students.objects(name = "Tom", class = "some way to say distinct?")
Though it does not appear to be documented. If this is not the syntactically correct way to do it, is this possible in mongoengine, or is there some way to accomplish with some other library like pymongo? Or do i have to query for all documents with Tom then do some post-processing to get to unique values? Syntax would be appreciated for any case.
First of all, it's only possible to get distinct values on some field (only one field) as explained in MongoDB documentation on Distinct.
Mongoengine's QuerySet class does support distinct() method to do the job.
So you might try something like this to get results:
Students.objects(name="Tom").distinct(field="class")
This query results in one BSON-document containing list of classes Tom attends.
Attention Note that returned value is a single document, so if it exceeds max document size (16 MB), you'll get error and in that case you have to switch to map/reduce approach to solve such kind of problems.
import pymongo
posts = pymongo.MongoClient('localhost', 27017)['db']['colection']
res = posts.find({ "geography": { "$regex": '/europe/', "$options": 'i'}}).distinct('geography')
print type(res)
res.sort()
for line in res:
print line
refer to http://docs.mongodb.org/manual/reference/method/db.collection.distinct/
distinct returns a list , will be printed on print type(res) , you can sort a list with res.sort() , after that it will print the values of the sorted list.
Also you can query posts before select distinct values .
student_users = Students.objects(name = "Tom").distinct('class')

creating a dictionary named as variable

I am using pyodbc to query database and retrieve some data (obviously).
What I would like is to create new dictionaries namd according to values returned from query.
For example I have a table with 1000 items, and one of collumns in that table is a INT number which is in range 1-51.
I want to do a rundown through my table, and create dictionaries named : bought_I, sold_I, created_I, etc... where I stands for INT number.
I hope I am clear enough :)
I know I could premade those dicts, but range will not always be 1-51, and it's nicer and cleaner to do it programmatically than to hardcode it.
Don't.
Create a dictionary bought, and give it keys based on your number:
bought = {}
for number in column_x:
bought[number] = "whatever object you need here"
Same for sold, created etc.
Or just one big dict:
mydict = {"bought": {}, "sold": {}, "created": {}}
for number in column_x:
for key in mydict:
mydict[key][number] = "whatever"

Categories