EDIT: Added example code at the bottom
I'm using dictionaries to keep track of two values for a given key. As an example, I want to keep track of how many balls and strikes a couple baseball players get. So I have two baseball players:
- Tim
- Mark
All of there stats are listed in a text file like:
- Tim gets a strike
- Tim gets a ball
- Tim gets a strike
- Mark gets a ball
And so on and so forth. So for the first line, the dictionary would like this (reflecting Tim getting a strike).
stats = {'tim', [1, 0]}
Then he gets a ball:
stats = {'tim', [1, 1]}
Then another strike:
stats = {'tim', [2, 1]}
Then Mark gets a ball:
stat = {'tim', [2, 1],
'mark', [0, 1]}
Started tackling this by creating two dictionaries (one for strikes, one for balls), but I ran into two problems:
When I attempted to append value from strikes to balls for one player I ran into the error:
TypeError: 'int' object is not iterable
I'm assuming this means append() doesn't work for integers, but I'm not sure. I also tried using str() to change the value, but ran into the same error.
- Even if I could solve this problem, I need to put in 0's when a strike or ball is not recorded.
Here's the general code I have at the moment:
#!/usr/bin/env python3
import re
strike = {}
ball = {}
with open("baseball_stats.txt", "r") as file:
for line in file:
player = re.search(r"^\s*([a-zA-Z] )", line)
name = player.group(1)
if "strike" in line:
if name in strike:
strike[name] = 1
else:
strike[name] = 1
else:
if name in ball:
ball[name] = 1
else:
ball[name] = 1
## This is where I tried to combine the tow into the Strike dictionary and add 0's when no strikes where recorded
for key, value in ball.items():
if key in strike.keys():
addBall = ball[key]
strike[key].append(addBall)
else:
strike[key] = 0
addBall = ball[key]
strike[key].append(addBall)
Basically, I think I'm going about this all wrong and figured I ask for guidance. Let me know if I need to elaborate on anything. Anything helps!
CodePudding user response:
If you plan on keeping more stats per player later, a nested dictionary is probably best. The defaultdict class (from collections) will make this easy to use.
Input:
events = ["Jim ball",
"Jim strike",
"Jim strike",
"Jim ball",
"Jim strike out",
"Tom ball",
"Tom hit out",
"Mark strike",
"Mark ball",
"Mark hit onBase" ]
Process:
from collections import defaultdict
players = defaultdict(lambda:defaultdict(int))
for event in events:
player,*keywords = event.split()
for stat in keywords:
players[player][stat] = 1
Output:
print(players)
defaultdict(<function <lambda> at 0x7fc0f9996400>,
{'Jim': defaultdict(<class 'int'>,
{'ball': 2, 'strike': 3, 'out': 1}),
'Tom': defaultdict(<class 'int'>,
{'ball': 1, 'hit': 1, 'out': 1}),
'Mark': defaultdict(<class 'int'>,
{'strike': 1, 'ball': 1, 'hit': 1, 'onBase': 1})
})
print(players['Jim']['ball']) # 2
print(sum(stats['strike'] for stats in players.values())) # 4
print(max(players,key=lambda p:players[p]['ball'])) # Jim
CodePudding user response:
This is my simple solution to your problem (and yes, you should post your code so people can try to help!):
events = [["Tim", "strike"],
["Tim", "ball"],
["Tim" , "strike"],
["Mark", "ball"]]
res = {}
for e in events:
player = res.get(e[0], [0, 0])
if e[1] == "strike":
player[0] = 1
elif e[1] == "ball":
player[1] = 1
res[e[0]] = player
print(res)