I have a bunch of code that is out of scope of this question. The code scrapes data and gives me the following dictionary:
{'Male Open 60 Mins': {'Kavin Jones': {'total_points': 47, 'plate_number': '35'}, 'Alan Smith': {'total_points': 42, 'plate_number': '23'}, 'Dominique Smith': {'total_points': 35, 'plate_number': '20'}, 'James Smith': {'total_points': 32, 'plate_number': '15'}, 'Hans Smith': {'total_points': 35, 'plate_number': '99'}, 'Cameron Smith': {'total_points': 33, 'plate_number': '21'}, 'Michael Smith': {'total_points': 23, 'plate_number': '148'}, 'Chris Smith': {'total_points': 32, 'plate_number': '18'}, 'Jackson Smith': {'total_points': 14, 'plate_number': '17'}, 'Grant Smith': {'total_points': 12, 'plate_number': '48'}, 'David Smith': {'total_points': 11, 'plate_number': '3'}, 'Andrew Smith': {'total_points': 23, 'plate_number': '32'}, 'Duncan Smith': {'total_points': 22, 'plate_number': '33'}, 'Brian Smith': {'total_points': 18, 'plate_number': '36'}, 'Manning Jones': {'total_points': 10, 'plate_number': '14'}, 'Matthew Smith': {'total_points': 15, 'plate_number': '27'}, 'Clifford Smith': {'total_points': 6, 'plate_number': '28'}, "Che'quan Smith": {'total_points': 4, 'plate_number': '34'}, 'Philip Smith': {'total_points': 9, 'plate_number': '43'}, 'Christopher Jones': {'total_points': 4, 'plate_number': '13'}, 'Wendell Smith': {'total_points': 5, 'plate_number': '2'}, 'Maceo Smith': {'total_points': 2, 'plate_number': '8'}, 'Craig Smith': {'total_points': 2, 'plate_number': '11'}, 'Dennis Smith': {'total_points': 2, 'plate_number': '10'}, 'Edwin Smith': {'total_points': 2, 'plate_number': '88'}, 'Dirk Smith': {'total_points': 2, 'plate_number': '142'}, 'Mark Smith': {'total_points': 12, 'plate_number': '46'}, 'Jay Smith': {'total_points': 2, 'plate_number': '25'}, 'Blake Smith': {'total_points': 2, 'plate_number': '178'}, 'Stephen Smith': {'total_points': 1, 'plate_number': '31'}, 'Justin Smith': {'total_points': 2, 'plate_number': '12'}, 'Peter Smith': {'total_points': 2, 'plate_number': '26'}, 'Jenai Smith': {'total_points': 1, 'plate_number': '29'}, 'Christopher Smith': {'total_points': 2, 'plate_number': '44'}, 'Nathan j. Smith': {'total_points': 2, 'plate_number': '39'}, 'Deryck Smith': {'total_points': 1, 'plate_number': '24'}, 'Conor Smith': {'total_points': 25, 'plate_number': '40'}, 'Moses Smith': {'total_points': 7, 'plate_number': '16'}, 'Howard Smith': {'total_points': 5, 'plate_number': '41'}, 'Chad Smith': {'total_points': 1, 'plate_number': '38'}}, 'Female Open 60 Mins': {'Jennifer Smith': {'total_points': 67, 'plate_number': '42'}, 'Ashley Smith': {'total_points': 40, 'plate_number': '6'}, 'Caitlin Smith': {'total_points': 25, 'plate_number': '5'}}}
I then run the following code to order each racer within each race by total_points
:
from collections import OrderedDict
from operator import getitem
for key in overall_standings.keys():
current_reorder = OrderedDict(sorted(overall_standings[key].items(), key = lambda x: getitem(x[1], 'total_points'), reverse=True))
overall_standings[key] = current_reorder
for item, racer_info in overall_standings.items():
print("\n********" item "********")
for name, data in racer_info.items():
print(name)
print(data['total_points'])
print(data['plate_number'])
If I print out the ordered dictionary now, it looks like this:
{'Male Open 60 Mins': OrderedDict([('Kavin Jones', {'total_points': 47, 'plate_number': '35'}), ('Alan Smith', {'total_points': 42, 'plate_number': '23'}), ('Dominique Smith', {'total_points': 35, 'plate_number': '20'}), ('Hans Smith', {'total_points': 35, 'plate_number': '99'}), ('Cameron Smith', {'total_points': 33, 'plate_number': '21'}), ('James Smith', {'total_points': 32, 'plate_number': '15'}), ('Chris Smith', {'total_points': 32, 'plate_number': '18'}), ('Conor Smith', {'total_points': 25, 'plate_number': '40'}), ('Michael Smith', {'total_points': 23, 'plate_number': '148'}), ('Andrew Smith', {'total_points': 23, 'plate_number': '32'}), ('Duncan Smith', {'total_points': 22, 'plate_number': '33'}), ('Brian Smith', {'total_points': 18, 'plate_number': '36'}), ('Matthew Smith', {'total_points': 15, 'plate_number': '27'}), ('Jackson Smith', {'total_points': 14, 'plate_number': '17'}), ('Grant Smith', {'total_points': 12, 'plate_number': '48'}), ('Mark Smith', {'total_points': 12, 'plate_number': '46'}), ('David Smith', {'total_points': 11, 'plate_number': '3'}), ('Manning Jones', {'total_points': 10, 'plate_number': '14'}), ('Philip Smith', {'total_points': 9, 'plate_number': '43'}), ('Moses Smith', {'total_points': 7, 'plate_number': '16'}), ('Clifford Smith', {'total_points': 6, 'plate_number': '28'}), ('Wendell Smith', {'total_points': 5, 'plate_number': '2'}), ('Howard Smith', {'total_points': 5, 'plate_number': '41'}), ("Che'quan Smith", {'total_points': 4, 'plate_number': '34'}), ('Christopher Jones', {'total_points': 4, 'plate_number': '13'}), ('Maceo Smith', {'total_points': 2, 'plate_number': '8'}), ('Craig Smith', {'total_points': 2, 'plate_number': '11'}), ('Dennis Smith', {'total_points': 2, 'plate_number': '10'}), ('Edwin Smith', {'total_points': 2, 'plate_number': '88'}), ('Dirk Smith', {'total_points': 2, 'plate_number': '142'}), ('Jay Smith', {'total_points': 2, 'plate_number': '25'}), ('Blake Smith', {'total_points': 2, 'plate_number': '178'}), ('Justin Smith', {'total_points': 2, 'plate_number': '12'}), ('Peter Smith', {'total_points': 2, 'plate_number': '26'}), ('Christopher Smith', {'total_points': 2, 'plate_number': '44'}), ('Nathan j. Smith', {'total_points': 2, 'plate_number': '39'}), ('Stephen Smith', {'total_points': 1, 'plate_number': '31'}), ('Jenai Smith', {'total_points': 1, 'plate_number': '29'}), ('Deryck Smith', {'total_points': 1, 'plate_number': '24'}), ('Chad Smith', {'total_points': 1, 'plate_number': '38'})]), 'Female Open 60 Mins': OrderedDict([('Jennifer Smith', {'total_points': 67, 'plate_number': '42'}), ('Ashley Smith', {'total_points': 40, 'plate_number': '6'}), ('Caitlin Smith', {'total_points': 25, 'plate_number': '5'}}}
I'm not sure how OrderedDict or sorted sorts the racers where they have the same number of points. You'll see that there are a bunch of racers where the total_points
are 2 and 1.
What I'm looking to do, is to add to the dictionary a key for each racer where it averages their race positions. Take Chad Smith for instance. Let's say that he came 10th, 11th, 10th, and 9th. I want to add a key where his race position average is 10. This is easy to do.
How do I take the OrderedDict now and say, for every duplicate in total_points
, I want to now sort by race position average? Would this code come during my primary OrderedDict and sorted code or would it come after?
CodePudding user response:
I learned that built into sorted
is a tuple value where you can sort by a secondary field if there is a tie in your first field.
I added the following lines to my code to allow for the list addition. If this racer is new, we create a var with the empty list.
if racer not in overall_standings[race_name]:
overall_standings[race_name][racer] = {}
if "average_position" not in overall_standings[race_name][racer]:
overall_standings[race_name][racer]["average_position"] = []
overall_standings[race_name][racer]["average_position"].append(position)
else:
overall_standings[race_name][racer]["average_position"].append(position)
Could you do this cleaner? Sure. But this works. Code clean-up comes later.
This would give me a dictionary that looks like:
{'Male Open 60 Mins': {'Kavin Smith': {'average_position': [1, 2], 'total_points': 47, 'plate_number': '35'}, 'Alan Potts': {'average_position': [2, 3], 'total_points': 42, 'plate_number': '23'}}}
I then averaged out the list:
for item, racer_info in overall_standings.items():
for name, data in racer_info.items():
data["average_position"] = sum(data["average_position"])/len(data["average_position"])
Finally I do the following from the code in my original question:
for key in overall_standings.keys():
current_reorder = OrderedDict(sorted(overall_standings[key].items(), key = lambda x: (getitem(x[1], 'total_points'), -getitem(x[1], 'average_position')), reverse=True))
overall_standings[key] = current_reorder
I do -getitem(x[1]
with a minus because you can only set the reverse=
switch once and while I want the total_points
to order from biggest to smallest, I want the average_position
to order from smallest to biggest (because if you and another racer both have 20 points, coming 1st beats coming 2nd overall).
Now I just access the data.
for item, racer_info in overall_standings.items():
print("\n------------" item "------------")
for name, data in racer_info.items():
print(name)
print("Total Points: " str(data['total_points']))
print("Plate Number: " str(data['plate_number']))
print("Average Position: " str(data['average_position']))
print("-----------------------")