问题
Considering the following list within it 4 tuples:
players_score = [ ('Joe', 100, 34, 38, 90, 67, 3, 10),
('Bob', 90, 38, 4, 100, 60, 4, 11),
('May', 80, 36, 40, 91, 70, 2, 12),
('Anna', 95, 32, 36, 92, 68, 8, 13) ]
The players have been playing 7 games. In the first game, Joe has won with 100 points.
I would like to score each player (of each game) according to the following:
First/best player: 5 points
Second player: 3 points
Third player: 1 point
Fourth player: -1 point -> But 0 points is what I like to assign the fourth player of each game.
My code so far:
from itertools import zip_longest as y
zipped = list(y(*[game_score for _, *game_score in players_score]))
tup = list(sorted(i, reverse=True) for i in zipped)
score_dict = {}
for player, *game_score in players_score:
tmp = []
for i,j in zip(game_score, tup):
tmp.append(5-2*j.index(i))
tot_score = sum(tmp)
score_dict[player] = tot_score
print("The overall scores are: ", sorted(score_dict.items(), key=lambda kv: (kv[1], kv[0]), reverse=True))
So, my code applies -1 points to the fourth player of each game, but instead, I want the fourth player to earn just 0 zero points. I'm struggling with applying a range ([0:3]) or another method by which I could skip the fourth player from getting a score because that player just earns 0 points.
回答1:
I would set this up a bit differently. That being said, there's more than one way to do this. The first thing I would do is turn that players_score
list into a prettier collection, like a dictionary - just so it's more fun to work with.
Basically, we iterate through our "rounds" (the games), and sort the player names based on their score in the current round (the winner of the current round comes first). Then we zip
the sorted player names with the respective reward (score) they deserve, and update our collections.Counter
collection, using the player name as the key.
from collections import Counter
players_score = [
("Joe", 100, 34, 38, 90, 67, 3, 10),
("Bob", 90, 38, 4, 100, 60, 4, 11),
("May", 80, 36, 40, 91, 70, 2, 12),
("Anna", 95, 32, 36, 92, 68, 8, 13)
]
original_scores = {player: scores for player, *scores in players_score}
def iter_score(player):
for score in original_scores[player]:
yield player, score
score_rewards = [5, 3, 1, 0]
overall_scores = Counter()
for current_round in zip(*map(iter_score, original_scores)):
sorted_players = map(lambda tpl: tpl[0], sorted(current_round, key=lambda tpl: tpl[1], reverse=True))
for player, score in zip(sorted_players, score_rewards):
overall_scores.update({player: score})
print("The overall scores:")
for player, score in overall_scores.most_common():
print(f"{player}: {score}")
Output:
The overall scores:
Anna: 20
May: 17
Bob: 15
Joe: 11
回答2:
you can change your scoring function:
tmp.append(5-2*j.index(i) if 5-2*j.index(i) > 0 else 0)
so if there is negative values set the score to 0
回答3:
A very simple solution
for i,j in zip(game_score, tup):
score_var = 5-2*j.index(i)
if (score_var < 0):
score_var = 0
tmp.append(score_var)
This will ensure that no player will earn negative points.
回答4:
Use max(0, x)
to ensure that the value is at least 0
:
tmp.append(max(0, 5-2*j.index(i)))
来源:https://stackoverflow.com/questions/59362077/how-to-iterate-with-range-using-itertools