python dictionary - how to search and display answers - python

I'm trying to use a database implemented as a dictionary to search for a user entered value and if that value is found, it is displayed or else an error message is displayed.
'uuc' or 'uum' etc refers to abbreviations for a university campus.
The user should be able to enter one of the above values and any matches should be displayed. However, this doesn't work in my code and I can't locate the problem.
def all_from(datab,university):
l = len(datab)
k = 1
i = 0
while k <= 1:
s = datab[k]
the_university = s[2]
if university == the_university:
i = i + 1
print datab[k]
k = k + 1
if i == 0:
print 'Nobody goes to University there!'
datab = dict()
datab[1] = ['walker','matthew','uuc',1]
datab[2] = ['stewart','rory','uum',2]
datab[3] = ['toner','kevin','qub',4]
datab[4] = ['hughes','johnny','uuj',1]
datab[5] = ['douglas','kenny','uuc', 3]
datab[6] = ['hooks', 'peter','qub',1]
datab[7] = ['campbell','vicky','uuj',2]
datab[8] = ['crooks','laura','uum',4]
datab[9] = ['irwin','emma','uuc',3]
datab[10] = ['patterson','steve','uuc',1]
university = (raw_input('Enter the University here: '))
all_from(datab,university)

My contribution. I feel that arranging the students as items in a list, with the different fields as dictionary keys is a better data structure.
def find_all(datab,uni):
for student in datab:
if student['uni'] == uni:
print(student)
datab = []
datab.append( {'lastname':'walker', 'firstname':'matthew','uni':'uuc','year':1})
datab.append( {'lastname':'stewart','firstname':'rory','uni':'uum','year':2})
datab.append( {'lastname':'toner','firstname':'kevin','uni':'qub','year':4})
datab.append( {'lastname':'hughes','firstname':'johnny','uni':'uuj','year':1})
uni = input('Enter the uni here: ')
find_all(datab,uni)
If you want to search through all the keys then you could change the
if student['uni'] == uni line to
for key, value in student.items():
if value == uni:
Another version: this will allow you to enter a very simple query.
def find_all(datab,query):
query = query.split('OR')
for search_terms in query:
for student in datab:
for key, value in student.items():
if value == search_terms.strip():
print(student)
datab = list()
datab.append( {'lastname':'walker', 'firstname':'matthew','uni':'uuc','year':'1'})
datab.append( {'lastname':'stewart','firstname':'rory','uni':'uum','year':'2'})
datab.append( {'lastname':'toner','firstname':'kevin','uni':'qub','year':'4'})
datab.append( {'lastname':'hughes','firstname':'johnny','uni':'uuj','year':'1'})
query = input('Enter your query here: ')
find_all(datab,query)
Here is my code running with two simple queries
Enter the uni here: uum OR uuc
{'firstname': 'rory', 'lastname': 'stewart', 'uni': 'uum', 'year': 2}
{'firstname': 'matthew', 'lastname': 'walker', 'uni': 'uuc', 'year': 1}
Enter your query here: 1 OR UUM
{'firstname': 'matthew', 'lastname': 'walker', 'uni': 'uuc', 'year': '1'}
{'firstname': 'johnny', 'lastname': 'hughes', 'uni': 'uuj', 'year': '1'}
You just add the word OR between the items and it will search for any item in the dictionary that contains any of the words. N.B. I had to change the uni year to be a string to get it working.
As I've stated. This would be much better with a proper database like SQLite.

You could simplify your all_from function:
def all_from(datab,university):
# Create flag to see if there are results
result = False
for k in datab.keys():
# Knowing that university will always be in the same column
if university == datab[k][2]:
result = True
print datab[k]
if not result:
print 'Nobody goes to University there!'
datab = dict()
datab[1] = ['walker','matthew','uuc',1]
datab[2] = ['stewart','rory','uum',2]
datab[3] = ['toner','kevin','qub',4]
datab[4] = ['hughes','johnny','uuj',1]
datab[5] = ['douglas','kenny','uuc', 3]
datab[6] = ['hooks', 'peter','qub',1]
datab[7] = ['campbell','vicky','uuj',2]
datab[8] = ['crooks','laura','uum',4]
datab[9] = ['irwin','emma','uuc',3]
datab[10] = ['patterson','steve','uuc',1]
university = (raw_input('Enter the University here: '))
all_from(datab,university)
http://www.codeskulptor.org/#user42_wjXMwt73xI_2.py

Related

Get the value of a specific record in dicts with lists in python

I have a dict like this:
contactos = dict([
"id", id,
"nombres", nombres,
"apellidos", apellidos,
"telefonos", telefonos,
"correos", correos
])
And it works when I put a new register in every key:value, my problem is, how can I get the record for only one contact?
I have a part where I can input a number and search the position in the list of the dict, then I want to only show the record of that specific record in every key:value
I made this code, but it doesn´t work.
telefo = input(Fore.LIGHTGREEN_EX + "TELEFONO CONTACTO: " + Fore.RESET)
for x in range(len(telefonos)):
if(telefonos[x] == telefo):
print(contactos["telefonos"][x])
else:
print("No encontrado")
I print only the telefono value, ´cause it´s my test code.
This should be your working script:
# I imagine your data to be somethig like this. If it isn't, sorry:
id = 0
nombres = ['John', 'Anna', 'Robert']
apellidos = ['J.', 'A.', 'Rob.']
telefonos = ['333-444', '222-111', '555-888']
correos = ['john#email.com', 'anna#email.com', 'rob#email.com']
# This is the part where you made it wrong.
# Dictionaries are created with {}
#
# [] creates a list, not a dictionary structure.
#
# Also, key and values must be grouped as:
# "key": value
contactos = dict({
"id": id,
"nombres": nombres,
"apellidos": apellidos,
"telefonos": telefonos,
"correos": correos
})
# Now, imagine this this is the input from user:
telefo = "333-444"
for x in range(len(telefonos)):
if (telefonos[x] == telefo):
print(contactos["telefonos"][x])
break
else:
print("No encontrado")
When testing the script, the output is 333-444.

Function : Updating & printing a dictionary with the most recent values

I've created a function : A dictionary which takes in city name and country name to which the city belongs to. Currently the code just returns a dictionary after each iteration with city name and country name after taking inputs using the input(). I'm trying to update the code (no success so far) so that a new dictionary is printed after each iteration with updated dictionary which returns an output like
{'city' : 'berlin', 'country' : 'germany',
'city' : 'paris', 'country' : 'france',}
The code is as follows :
def city_country(city_name, country_name):
pair = {'City': city_name, 'Country': country_name}
return pair
active = True
while active:
user_city = input("Enter city name : ")
if user_city == 'q':
break
user_country = input("Enter country name : ")
if user_country == 'q':
break
new_pair = city_country(user_city, user_country)
print(new_pair)
The keys of the dictionary type are unique, this way of writing you can always print only one city and one country, maybe you can try to do it in json format, but it means you have to write another function to deal with the duplication of data (directly add or replace)
def city_country(city_name, country_name):
return {'City': city_name, 'Country': country_name}
data = []
while True:
user_city = input("Enter city name : ")
if user_city == 'q':
break
user_country = input("Enter country name : ")
if user_country == 'q':
break
data.append(city_country(user_city, user_country))
print(data)
city_country_dict = {}
active = True
while active:
user_city = input("Enter city name : ")
if user_city == 'q':
break
user_country = input("Enter country name : ")
if user_country == 'q':
break
new_pair = city_country(user_city, user_country)
#=================================
city_country_dict.update(new_pair)
#=================================
print(city_country_dict)

I need help on how to save dictionary elements into a csv file

I intend to save a contact list with name and phone number in a .csv file from user input through a dictionary.
The problem is that only the name is saved on the .csv file and the number is omitted.
contacts={}
def phone_book():
running=True
while running:
command=input('A(dd D)elete L)ook up Q)uit: ')
if command=='A' or command=='a':
name=input('Enter new name: ')
print('Enter new number for', name, end=':' )
number=input()
contacts[name]=number
elif command=='D' or command=='d':
name= input('Enter the name to delete: ')
del contacts[name]
elif command=='L' or command=='l':
name= input('Enter name to search: ')
if name in contacts:
print(name, contacts[name])
else:
print("The name is not in the phone book, use A or a to save")
elif command=='Q' or command=='q':
running= False
elif command =='list':
for k,v in contacts.items():
print(k,v)
else:
print(command, 'is not a valid command')
def contact_saver():
import csv
global name
csv_columns=['Name', 'Phone number']
r=[contacts]
with open(r'C:\Users\Rigelsolutions\Documents\numbersaver.csv', 'w') as f:
dict_writer=csv.writer(f)
dict_writer.writerow(csv_columns)
for data in r:
dict_writer.writerow(data)
phone_book()
contact_saver()
as I am reading your code contacts will look like
{
'name1': '1',
'name2': '2'
}
keys are the names and the value is the number.
but when you did r = [contacts] and iterating over r for data in r that will mess up I guess your code since you are passing dictionary value to writerow instead of a list [name, number]
You can do two things here. parse properly the contacts by:
for k, v in contacts.items():
dict_writer.writerow([k, v])
Or properly construct the contacts into a list with dictionaries inside
[{
'name': 'name1',
'number': 1
}]
so you can create DictWriter
fieldnames = ['name', 'number']
writer = csv.DictWriter(f, fieldnames=fieldnames)
...
# then you can insert by
for contact in contacts:
writer.writerow(contact) # which should look like writer.writerow({'name': 'name1', 'number': 1})

Linking two lists based on a common value and

I am new to Python 2.7 and I want the 1st column as the key column in employees and it has to check on dept 1st column and generate results.
Employees comes from a text file and dept comes from a database. I tried a lot but didn't get an easy answer. What is wrong with my code?
**Inputs :**
employees=['1','peter','london']
employees=['2','conor','london']
employees=['3','ciara','london']
employees=['4','rix','london']
dept=['1','account']
dept=['2','developer']
dept=['3','hr']
**Expected Output :**
results=['1','peter','london','account']
results=['2','conor','london','developer']
results=['3','ciara','london','hr']
results=['4','rix','london',null]
your input makes no sense. Each line overwrites the previous one data-wise. Here it seems that the digits (as string) are the keys, and some default action must be done when no info is found in dept.
To keep the spirit, just create 2 dictionaries, then use dictionary comprehension to generate the result:
employees = dict()
dept = dict()
employees['1'] = ['peter','london']
employees['2'] = ['conor','london']
employees['3'] = ['ciara','london']
employees['4'] = ['rix','london']
dept['1']=['account']
dept['2']=['developer']
dept['3']=['hr']
result = {k:v+dept.get(k,[None]) for k,v in employees.items()}
print(result)
which yields a dictionary with all the info. Note that null is None in python:
{'1': ['peter', 'london', 'account'], '4': ['rix', 'london', None], '3': ['ciara', 'london', 'hr'], '2': ['conor', 'london', 'developer']}
You could go for a class. Consider this:
class Employee:
def __init__(self, number, name, location, dept):
self.number = str(number)
self.name = name
self.location = location
self.dept = dept
def data(self):
return [self.number,
self.name,
self.location,
self.dept]
peter = Employee(1, 'peter', 'london', 'account')
print(peter.data())
['1', 'peter', 'london', 'account']
>>>

Consolidating row data from DB into a list of dicts

I'm reading data from a SELECT statement of SQLite. Date comes in the following form:
ID|Phone|Email|Status|Role
Multiple rows may be returned for the same ID, Phone, or Email. And for a given row, either Phone or Email can be empty/NULL. However, for the same ID, it's always the same value for Status and the same for Role. for example:
1|1234567892|a#email.com| active |typeA
2|3434567893|b#email.com| active |typeB
2|3434567893|c#email.com| active |typeB
3|5664567891|d#email.com|inactive|typeC
3|7942367891|d#email.com|inactive|typeC
4|5342234233| NULL | active |typeD
5| NULL |e#email.com| active |typeD
These data are returned as a list by Sqlite3, let's call it results. I need to go through them and reorganize the data to construct another list structure in Python. The final list basically consolidates the data for each ID, such that:
Each item of the final list is a dict, one for each unique ID in results. In other words, multiple rows for the same ID will be merged.
Each dict contains these keys: 'id', 'phones', 'emails', 'types', 'role', 'status'.
'phones' and 'emails' are lists, and contains zero or more items, but no duplicates.
'types' is also a list, and contains either 'phone' or 'email' or both, but no duplicates.
The order of dicts in the final list does not matter.
So far I have come up this:
processed = {}
for r in results:
if r['ID'] in processed:
p_data = processed[r['ID']]
if r['Phone']:
p_data['phones'].add(r['Phone'])
p_data['types'].add('phone')
if r['Email']:
p_data['emails'].add(r['Email'])
p_data['types'].add('email')
else:
p_data = {'id': r['ID'], 'status': r['Status'], 'role': r['Role']}
if r['Phone']:
p_data['phones'] = set([r['Phone']])
p_data.setdefault('types', set).add('phone')
if r['Email']:
p_data['emails'] = set([r['Email']])
p_data.setdefault('types', set).add('email')
processed[r['ID']] = p_data
consolidated = list(processed.values())
I wonder if there is a faster and/or more concise way to do this.
EDIT:
A final detail: I would prefer to have 'phones', 'emails', and 'types' in each dict as list instead of set. The reason is that I need to dump consolidated into JSON, and JSON does not allow set.
When faced with something like this I usually use:
processed = collections.defaultdict(lambda:{'phone':set(),'email':set(),'status':None,'type':set()})
and then something like:
for r in results:
for field in ['Phone','Email']:
if r[field]:
processed[r['ID']][field.lower()].add(r[field])
processed[r['ID']]['type'].add(field.lower())
Finally, you can dump it into a dictionary or a list:
a_list = processed.items()
a_dict = dict(a_list)
Regarding the JSON problem with sets, you can either convert the sets to lists right before serializing or write a custom encoder (very useful!). Here is an example of one I have for dates extended to handle sets:
class JSONDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return int(time.mktime(obj.timetuple()))
elif isinstance(ojb, set):
return list(obj)
try:
return json.JSONEncoder.default(self, obj)
except:
return str(obj)
and to use it:
json.dumps(a_list,sort_keys=True, indent=2, cls =JSONDateTimeEncoder)
I assume results is a 2d list:
print results
#[['1', '1234567892', 'a#email.com', ' active ', 'typeA'],
#['2', '3434567893', 'b#email.com', ' active ', 'typeB'],
#['2', '3434567893', 'c#email.com', ' active ', 'typeB'],
#['3', '5664567891', 'd#email.com', 'inactive', 'typeC'],
#['3', '7942367891', 'd#email.com', 'inactive', 'typeC'],
#['4', '5342234233', ' NULL ', ' active ', 'typeD'],
#['5', ' NULL ', 'e#email.com', ' active ', 'typeD']]
Now we group this list by id:
from itertools import groupby
data_grouped = [ (k,list(v)) for k,v in groupby( sorted(results, key=lambda x:x[0]) , lambda x : x[0] )]
# make list of column names (should correspond to results). These will be dict keys
names = [ 'id', 'phone','email', 'status', 'roll' ]
ID_info = { g[0]: {names[i]: list(list( map( set, zip(*g[1] )))[i]) for i in range( len(names))} for g in data_grouped }
Now for the types:
for k in ID_info:
email = [ i for i in ID_info[k]['email'] if i.strip() != 'NULL' and i != '']
phone = [ i for i in ID_info[k]['phone'] if i.strip() != 'NULL' and i != '']
if email and phone:
ID_info[k]['types'] = [ 'phone', 'email' ]
elif email and not phone:
ID_info[k]['types'] = ['email']
elif phone and not email:
ID_info[k]['types'] = ['phone']
else:
ID_info[k]['types'] = []
# project
ID_info[k]['id'] = ID_info[k]['id'][0]
ID_info[k]['roll'] = ID_info[k]['roll'][0]
ID_info[k]['status'] = ID_info[k]['status'][0]
And what you asked for (a list of dicts) is returned by ID_info.values()

Categories

Resources