I have almost finished my project for creating a scoreboard based on user input. However, when it comes to my last step, sorting based on the results given, my code does not seem to function. The output that I receive is as follows:
["player_result(name='Trees', points=0.5, resistance_points=2.0, sonnenborn_berger=0.5, black=1)", "player_result(name='Erik', points=1.0, resistance_points=1.5, sonnenborn_berger=0.75, black=1)", "player_result(name='Udo', points=1.0, resistance_points=2.0, sonnenborn_berger=1.0, black=1)", "player_result(name='Ronald', points=1.0, resistance_points=2.5, sonnenborn_berger=1.25, black=1)", "player_result(name='Truus', points=1.0, resistance_points=2.0, sonnenborn_berger=0.0, black=1)", "player_result(name='Omar', points=0.0, resistance_points=2.0, sonnenborn_berger=0, black=1)", "player_result(name='Cornelis', points=1.0, resistance_points=1.5, sonnenborn_berger=0.0, black=1)", "player_result(name='Ria', points=1.5, resistance_points=2.5, sonnenborn_berger=1.75, black=1)", "player_result(name='Otto', points=1.0, resistance_points=2.0, sonnenborn_berger=1.0, black=1)", "player_result(name='Emma', points=1.0, resistance_points=2.0, sonnenborn_berger=1.0, black=1)", "player_result(name='Henk', points=1.5, resistance_points=2.0, sonnenborn_berger=1.5, black=1)", "player_result(name='Ulrich', points=1.0, resistance_points=2.0, sonnenborn_berger=0.5, black=1)", "player_result(name='Cor', points=1.5, resistance_points=2.5, sonnenborn_berger=1.75, black=1)", "player_result(name='Piet', points=1.0, resistance_points=1.5, sonnenborn_berger=0.0, black=1)", "player_result(name='Theo', points=2.0, resistance_points=1.0, sonnenborn_berger=1.0, black=0)", "player_result(name='Thea', points=0.0, resistance_points=3.0, sonnenborn_berger=0, black=2)"]
What I would like to see is that these items are sorted from highest to lowest in the following order: points, resistance-points, sonnenborn-berger, black.
I have looked into the Sorting HOW TO documentation, on which I based the 2 sorted() lines in my code. However, the sorted(print_list) line gives no errors, but does not sort, and the sorted(return_list) line gives the following error.
Traceback (most recent call last):
File "{file}", line 70, in <module>
determine_output("""Trees
File "{file}", line 65, in determine_output
sorted_return_list = sorted(return_list, key=itemgetter(1, 2, 3, 4), reverse=True)
TypeError: 'player_result' object is not subscriptable
My question: how can I sort my class objects based on the attributes mentioned above? I am more 'concerned' that the return value is sorted as expected; the print value is to make the sorting 'visible to me'. For full clarity, my code is as follows:
from operator import itemgetter
class player_result:
def __init__(self, name: str, points: float, resistance_points: float, sonnenborn_berger: float, black: int):
self.name = name
self.points = points
self.resistance_points = resistance_points
self.sonnenborn_berger = sonnenborn_berger
self.black = black
def __str__(self):
return 'player_result(name=\'' self.name '\', points=' str(self.points) ', resistance_points=' \
str(self.resistance_points) ', sonnenborn_berger=' str(self.sonnenborn_berger) \
', black=' str(self.black) ')'
def __eq__(self, other):
return self.name == other.name and self.points == other.points and \
self.resistance_points == other.resistance_points and \
self.sonnenborn_berger == other.sonnenborn_berger and self.black == other.black
def determine_output(input: str):
# splitten van lijnen
splits = input.split("\n\n")
rounds = [i.split('\n') for i in splits]
# bepalen van players
players = {}
for name in rounds[0]:
players[name] = player_result(name, 0, 0, 0, 0)
# bepalen van points van iedere player
for one_round in rounds[1:]:
for game in one_round:
white_player, black_player, result_white_player, result_black_player = game.split()
players[white_player].points = float(result_white_player)
players[black_player].points = float(result_black_player)
players[black_player].black = 1
# bepalen van resistance_points van iedere player
# Uitleg: totaalscore van alle tegenstanders per speler toevoegen aan player
for one_round in rounds[1:]:
for game in one_round:
white_player, black_player, result_white_player, result_black_player = game.split()
players[white_player].resistance_points = players[black_player].points
players[black_player].resistance_points = players[white_player].points
# bepalen van sonneborn_berger van iedere player
# Uitleg: 1 * punten van verliezers 0,5 * punten van gelijk toevoegen aan player
for one_round in rounds[1:]:
for game in one_round:
white_player, black_player, result_white_player, result_black_player = game.split()
if float(result_white_player) == 1:
players[white_player].sonnenborn_berger = 1 * players[black_player].points
if float(result_white_player) == 0.5:
players[white_player].sonnenborn_berger = 0.5 * players[black_player].points
if float(result_black_player) == 1:
players[black_player].sonnenborn_berger = 1 * players[white_player].points
if float(result_black_player) == 0.5:
players[black_player].sonnenborn_berger = 0.5 * players[white_player].points
# sorteren: points > resistance_points > sonneborn_berger > black (van hoog naar laag)
print_list = []
return_list = []
for player in players.values():
print_list.append(str(player))
return_list.append(player)
print_list = sorted(print_list, key=itemgetter(1, 2, 3, 4), reverse=True)
return_list = sorted(return_list, key=itemgetter(1, 2, 3, 4), reverse=True)
print(print_list)
return return_list
determine_output("""Trees
Erik
Udo
Ronald
Truus
Omar
Cornelis
Ria
Otto
Emma
Henk
Ulrich
Cor
Piet
Theo
Thea
Trees Erik 0.5 0.5
Udo Ronald 0.5 0.5
Truus Omar 1 0
Cornelis Ria 0 1
Otto Emma 0.5 0.5
Henk Ulrich 1 0
Cor Piet 1 0
Theo Thea 1 0
Ria Cor 0.5 0.5
Theo Truus 1 0
Ronald Henk 0.5 0.5
Emma Udo 0.5 0.5
Erik Otto 0.5 0.5
Ulrich Trees 1 0
Piet Thea 1 0
Omar Cornelis 0 1""")
CodePudding user response:
There are multiple problems with your code.
To resolve the error, you can use attrgetter()
instead of itemgetter()
. It works similarly, but is used to get attributes, not items.
You seem to confuse the two. Attributes are usually belong to objects, and are accessed by the dot-syntax: result.name
. Items are usually belong to sequences (lists, tuples, etc.) and are accessed via the my_list[item_index]
syntax. Objects of your class have attributes, not items.
The other problem is the sorting of the print and returns lists. The print_list
sorting does not error out, even tho you used the same method for sorting them, but also won't get sorted correctly. The issue is, that the list does not contain player_result
instances, but strings. This also means the itemgetter
works on them, as they are sequences - but result in some strange alphabetic ordering instead of the intended. To fix it, you should sort the list before converting to str
(and like that, you only need to sort the data once).