Comparing 2 dictionaries in python - python

I have two dictionaries in Python. One is a list of teams and their ranks in a league table, with each team being a key and their ranks being the associated value. The other is data about each team, with the team name being a value of a key:
RankDict = {'Tigers':'1','Lions':'2', 'Pumas':'3', 'Wolves':'4'}
TeamDict = {'TeamRecords':[{'Team': 'Lions', 'Location':'Greenville',
'HomeGround':'Trec Park', 'Coach': 'K. Wilson'},
{'Team':'Pumas', 'Location':'Fairlodge',
'HomeGround':'Fairlodge Fields', 'Coach':'G. Kennedy'}]}
What I want to do is print the details from the TeamDict dictionary based on the rank associated with the team in the RankDict but can't just do a straight key comparison because the keys aren't common. Can anyone help me out?
I can't find anything regarding this type of dictionary comparison in the documentation. Maybe it isn't even possible?

The following will print the team, the rank and the team details (sorted by rank):
import operator
RecordsByTeam = {}
for r in TeamDict['TeamRecords']:
RecordsByTeam[r['Team']] = r
for team, rank in sorted(RankDict.items(), key=operator.itemgetter(1)):
print team
print rank
try:
print RecordsByTeam[team]
except KeyError:
print 'No details could be found for team', team
Note that I'm doing a try/except when printing the team details because TeamDict does not contain information about each team.
Also note that you should use integers for the ranks in RankDict, otherwise the above code won't sort properly when there is a team with, e.g., '11' as rank (it will sort: '11', '2', '3', '4').

Related

Accessing individual values from one key (dictionary)

people = {"Jenn" : ['renter', 'large room'],
"Lana" : ['renter', 'small room'],
"Ricky" :['owner', 'large room']
}
Is there a way to access each individual value for a given key via for loop to print the stats of each person? I'm relatively new to Python and I'm having troubles searching for this exact scenario. I'm familiar with f-string formatting.
Expected output for print() or sys.stderr.write()
Jenn is the renter of a large room.
Lana is the renter of a small room.
Rickey is the owner of a large room.
Use dict.items() to loop through (key, value) tuples:
for key, value in people.items():
print(f"{key} is the {value[0]} of a {value[1]}")
You can also do that:
for first, (cat, room) in people.items():
print(f"{first} is the {cat} of a {room} room")

nesting multiple dictionaries, possibly lists?

I am trying to build a python program to take a users input of the year of the car, and after that the model (no need for the make it will only contain fords). And with the year and model, the program will reference to the correct year and model and get the corresponding capacity information of the vehicle (engine oil, coolant, brake fluid etc.).
My question comes in with, how do I go about storing that information?
I was thinking to make a car_list dict and to the key years nest the first year 1998 inside that nest a list of the cars in that year, and in each car nest a dictionary of the specs.
car_list = {'years' : {1998 : [{'accord': {'oil' : '4.0 qts', 'coolant': '2 gals'} 'civic': {'oil': '4.5 qts', 'coolant': '3 gals'}]}
Will this work? Am I going about this wrong?
Simple program that may solve your problem (in python3):
model=input("model:")
year=input("year:")
query={model1:{year1:specs1,year2:specs2 ... }, model2:{ ... } ... }
print(query[model][year])
The specs could be either list or dictionary. It depends on how you want to use the data.
The program would prompt for user input and then print you the specs of the intended year and model as either a list or a dictionary. The output should be manipulated to fit your needs.
Using dictionary is a good idea here. But your code doesn't look right. Use this format:
car_list = {'1998' : {'accord': {'oil' : '4.0 qts', 'coolant': '2 gals'}, 'civic': {'oil': '4.5 qts', 'coolant': '3 gals'}}}
print(car_list['1998']['civic']['oil'])
You can store all the information in a nested dictionary, I think that's the best way. The dictionary can look like this:
car_list = {"1998":{"ka":["4.0 qts", "2 gals"],
"fiesta":["3.0 qts", "2.3 gals"]},
"2001":{"kuga":["3.3 qts", "3 gals"],
"mondeo":["4.0 qts", "3.5 gals"]}}
If you ask the user via input() for the year and car, you can print the information all by once if you use a for-loop:
input_year = input("Year?\n> ")
input_car = input("Car?\n> ")
for info in car_list[input_year][input_car]:
print(info)
or give them the information one by one:
input_year = input("Year?\n> ")
input_car = input("Car?\n> ")
i = car_list[input_year][input_car]
print("Oil: {}\nCoolant: {}".format(i[0], i[1]))

Searching for Phrase Keywords in MySQL

I have a table which has two columns: ID (primary key, auto increment) and keyword (text, full-text index).
The values entered in the keyword column include the following:
keyword
Car
Car sales
Cars
Sports cars
Sports foo
Car bar
Statistics
Suppose that we have this sentence as an input:
"Find sports car sales statistics in Manhattan."
I'm looking (and I have been searching for quite a while) to find either a MySQL query or an algorithm which takes in the given input, and detects the keywords used from the keywords column, resulting in an output of:
"Sports cars", "Car sales", "Statistics"
In other words, I'm trying to take an input that's in the form of a sentence, and then match all the existing (and most relevant) keyword values in the database that are found in the sentence. Note that these keywords could be phrases that consist of words separated by a space.
After researching I got to know that MySQL does a similar job through its full-text search feature. I have tried all the natural language, boolean, and query expansion options, but they include keyword records that only have half of its contents matching with the input. For example, it outputs:
"Car", "Car sales", "Sports cars", "Sports foo", "Cars bar", "Statistics".
I don't want this to happen because it includes words that aren't even in the input (i.e. foo and bar).
Here's the MySQL query for the above mentioned search:
SELECT * FROM tags WHERE MATCH(keyword) AGAINST('Find sports car sales statistics in Manhattan.' IN BOOLEAN MODE)
I also tried to improve on the relevancy, but this one only returns a single record:
SELECT *, SUM(MATCH(keyword) AGAINST('Find sports car sales statistics in Manhattan.' IN BOOLEAN MODE)) as score FROM tags WHERE MATCH(keyword) AGAINST('Find sports car sales statistics in Manhattan.' IN BOOLEAN MODE) ORDER BY score DESC
If we suppose that you have your column in a list as a pythonic way for such tasks you can use set.intersection to get the intersection between two set (the second element could be another iterables like list or tuple) :
>>> col={'Car','Car sales','Cars','Sports cars','Sports foo','Car bar','Statistics'}
>>> col={i.lower() for i in col}
>>> s="Find sports car sales statistics in Manhattan."
>>> col.intersection(s.strip('.').split())
set(['car', 'statistics'])
And in your case you can put the result of your query within a set or convert it to set.
Note : the following set comprehension will convert the elements if your column to lower case :
>>> col={i.lower() for i in col}
But this recipe will find the intersection between your column and the splitted string with white spaces. so the result will be :
set(['car', 'statistics'])
As another way you can use re.search :
>>> col={'Car','Car sales','Cars','Sports cars','Sports foo','Car bar','Statistics'}
>>> s='Find sports car sales statistics in Manhattan.'
>>> for i in col:
... g=re.search('{}'.format(i),s,re.IGNORECASE)
... if g:
... print g.group(0)
...
statistics
car sales
car
As a simple way you can use a function like following to get a combinations of your phrases :
from itertools import permutations
def combs(phrase):
sp=phrase.split()
com1=[map(lambda x:' '.join(x),li) for li in [permutations(sp,j) for j in range(1,len(sp)+1)]]
for i,k in enumerate(sp):
if not k.endswith('s'):
sp[i]=k+'s'
com2=[map(lambda x:' '.join(x),li) for li in [permutations(sp,j) for j in range(1,len(sp)+1)]]
return com1+com2
print {j for i in combs('Car sales') for j in i}
set(['Car', 'sales', 'sales Cars', 'Car sales', 'Cars sales', 'sales Car', 'Cars'])
Note that this function could be more efficient and complete.

comparing nested lists and editing

Sorry if this sounds like a silly question but this problem has gotten me really confused. I'm fairly new to python, so maybe I'm missing something. I did some research but haven't gotten too far. Here goes:
I'm going to use a simple example that makes the question clearer, my data is different but the format and required action is the same. We have a database of people and the pizzas they eat (and some other data). Our database however has multiple entries of the same people with different pizzas (because we combined data gotten from different pizzerias).
example dataset:
allData = [['joe','32', 'pepperoni,cheese'],['marc','24','cheese'],['jill','27','veggie supreme, cheese'],['joe','32','pepperoni,veggie supreme']['marc','25','cheese,chicken supreme']]
Few things we notice and rules I want to follow:
names can appear multiple times though in this specific case we KNOW that any entries with the same name is the same person.
the age can be different for the same person in different entries, so we just pick the first age we encountered of the person and use it. example marc's age is 24 and we ignore the 25 from the second entry
I want to edit the data so that a person's name only appears ONCE, and the pizzas he eats is a unique set from all entries with the same name. As mentioned before the age is just the first one encountered. Therefore, i'd want the final data to look like this:
fixedData = [['joe','32','pepperoni,cheese,veggie supreme'],['marc','24','cheese,chicken supreme'],['jill','27','veggie supreme, cheese']]
I'm thinking something on the lines of:
fixedData = []
for i in allData:
if i[0] not in fixedData[0]:
fixedData.append[i]
else:
fixedData[i[-1]]=set(fixedData[i[-1]],i[-1])
I know I'm making several mistakes. could you please please point me towards the right direction?
Thanks heaps.
Since names are unique, it makes sense to use them as keys in a dict, where the name is the key. This will be much more appropriate in your case:
>>> d = {}
>>> for i in allData:
if i[0] in d:
d[i[0]][-1] = list(set(d[i[0]][-1] + (i[-1].split(','))))
else:
d[i[0]] = [i[1],i[2].split(',')]
>>> d
{'jill': ['27', ['veggie supreme', ' cheese']], 'joe': ['32', ['pepperoni', 'cheese', 'pepperoni', 'veggie supreme']], 'marc': ['24', ['cheese', 'cheese', 'chicken supreme']]}
In cases like yours i like to use defaultdict. I really hate the guesswork that comes with list indexes.
from collections import defaultdict
allData = [['joe', '32', 'pepperoni,cheese'],
['marc', '24', 'cheese'],
['jill', '27', 'veggie supreme, cheese'],
['joe', '32', 'pepperoni,veggie supreme'],
['marc', '25', 'cheese,chicken supreme']]
d = defaultdict(dict)
for name, age, pizzas in allData:
d[name].setdefault('age', age)
d[name].setdefault('pizzas', set())
d[name]['pizzas'] |= set(pizzas.split(','))
Notice the usage of setdefault to set the first age value we encounter. It also enables the use of set union to get the unique pizzas.

Print a tupe key dictionary with multiple values

I have a dictionary with the last and first names of the authors being the key, and the book, quantity, and price being the values. I want to print them out sorted in alphabetical order by the author name, and then by the book name.
The author is: Dickens, Charles
The title is: Hard Times
The qty is: 7
The price is: 27.00
----
The author is: Shakespeare, William
The title is: Macbeth
The qty is: 3
The price is: 7.99
----
The title is: Romeo And Juliet
The qty is: 5
The price is: 5.99
I'm very new to dictionaries and can't understand how you can sort a dictionary. My code so far is this:
def displayInventory(theInventory):
theInventory = readDatabase(theInventory)
for key in theInventory:
for num in theInventory[key]:
print("The author is", ' '.join(str(n) for n in key))
print(' '.join(str(n) for n in num), '\n')
The dictionary, when printed, from which I read this looks like this:
defaultdict(<class 'list'>, {('Shakespeare', 'William'): [['Rome And Juliet', '5', '5.99'], ['Macbeth', '3', '7.99']], ('Dickens', 'Charles'): [['Hard Times', '7', '27.00']]})
fwiw, camelCase is very uncommon in Python; almost everything is written in snake_case. :)
I would do this:
for names, books in sorted(inventory.items()):
for title, qty, price in sorted(books):
print("The author is {0}".format(", ".join(names)))
print(
"The book is {0}, and I've got {1} of them for {2} each"
.format(title, qty, price))
print()
Ignoring for the moment that not everyone has a first and last name...
There are some minor tricks involved here.
First, inventory.items() produces a list of key, value tuples. I can then sort that directly, because tuples sort element-wise — that is, (1, "z") sorts before (2, "a"). So Python will compare the keys first, and the keys are tuples themselves, so it'll compare last names and then first names. Exactly what you want.
I can likewise sort books directly because I actually want to sort by title, and the title is the first thing in each structure.
I can .join the names tuple directly, because I already know everything in it should be a string, and something is wrong if that's not the case.
Then I use .format() everywhere because str() is a bit ugly.
The key is to use sorted() to sort the dictionary by its keys, but then use sort() on the dictionaries values. This is necessary because your values are actually a list of lists and it seems you want only to sort them by the first value in each sub-list.
theInventory = {('Shakespeare', 'William'): [['Rome And Juliet', '5', '5.99'], ['Macbeth', '3', '7.99']], ('Dickens', 'Charles'): [['Hard Times', '7', '27.00']]}
for Author in sorted(theInventory.keys()):
Author_Last_First = Author[0]+", "+Author[1]
Titles = theInventory[Author]
Titles.sort(key=lambda x: x[0])
for Title in Titles:
print("Author: "+str(Author_Last_First))
print("Title: "+str(Title[0]))
print("Qty: "+str(Title[1]))
print("Price: "+str(Title[2]))
print("\n")
Is that what you had in mind? You can of course always put this in a function to make calling it easier.

Categories

Resources