Here is the code:
import random
import sys
name = input("What is your name: ")
tri = 0
def rep():
score = random.randint(1,10)
total = 0
print ("score is",score,)
total = +score
file = open("1.txt","a")
file.write(str(name + " = "))
file.write(str(total))
file.write("\n")
file.close()
tri = +1
rep()
while tri > 2:
sys.exit
else:
print(rep())
So what this code does, is generates a random score for the user 2 times and then that score is saved into a .txt file under the users name which is inputted as 'name'. What I want to do is, if the same person did the game again and another 2 scores where generated it would overwrite the previous 2 results with the new two.
Here is what the text file would look like:
Tom = 2
Tom = 7
Chrissy = 3
Chirssy = 10
John = 4
John = 9
If the the user 'Tom' did the game again this time getting 5 and 3, the text file should look like the following:
Chrissy = 3
Chirssy = 10
John = 4
John = 9
Tom = 5
Tom = 3
In this current situation it just keeps adding on the scores like this:
Tom = 2
Tom = 7
Chrissy = 3
Chirssy = 10
John = 4
John = 9
Tom = 5
Tom = 3
A first comment, it's a really good idea to use the context managers for file operations, this will ensure that file resources are properly handled. For this reason I use it in the code here, I suggest you do the same.
If you are going to approach this in such a way that you want to use plain text files you have to remove the lines that contained the name then update. A function such as the following is likely going to help here:
def remove_old_names(name, filename):
"""Remove a line containing a specific name"""
with open(filename, 'r') as old_file:
lines = old_file.readlines()
with open(filename, 'w') as new_file:
for line in lines:
if name not in line:
new_file.write(line)
Then later when you can clear out the old names then append to the text file:
remove_old_names(name, filename)
with open("1.txt","a") as results:
results.write(str(name + " = "))
results.write(str(total))
results.write("\n")
Note the use of "a" here to open the file in append mode. If you open with "w" you can end up truncating the file.
Now if I was to approach this in a more structured way I would create a dictionary that stores the data:
results = dict()
results["bob"] = 2
And so forth for the other user names. I would then serialize this dictionary to a file using pickle or the JSON library.
For example with JSON library you get something like this:
import json
test = {
"bob": 1,
"joe": 2,
"jane": 3,
}
print(json.dumps(test, sort_keys=True, indent=4))
output:
{
"bob": 1,
"jane": 3,
"joe": 2
}
This is an easy file format to just do by hand. The one issue is that text files aren't really stored as lines so you can't just modify just one line. Once you've changed a line, everything after that must be rewritten to the file. If the file isn't too big, you just read everything into a list and work off of that.
import random
def rep(name, score1, score2):
try:
# read entire file into list
with open('1.txt') as fp:
lines = fp.readlines()
except FileNotFoundError:
lines = []
name_lower = name.lower()
for index, line in enumerate(lines):
if line.split('=')[0].strip().lower() == name_lower:
# found our match... next line had better be the same player
if lines[index+1].split('=')[0].strip().lower() != name_lower:
raise RuntimeError("File corrupted")
# replace user in the list
lines[index] = "{} = {}\n".format(name, score1)
lines[index + 1] = "{} = {}\n".format(name, score2)
# no need to process further
break
else:
# add new user
lines.append("{} = {}\n".format(name, score1))
lines.append("{} = {}\n".format(name, score2))
with open('1.txt', 'w') as fp:
fp.writelines(lines)
name = input("what is your name: ")
rep(name, random.choice(range(100)), random.choice(range(100)))
print(open('1.txt').read()) # debug
Related
f = open('studMarks.txt', 'r')
marks = 0
# Sort out names, split the words then sort which order
for line in f:
words = line.split()
fname = words[0]
lname = words[1]
print(f"{lname},{fname}")
f.close()
f = open('studMarks.txt', 'r')
sum = 0
count = 0
for line in f:
count += 1
sum += float(line.split()[2])
n = []
average = sum/count
print(f"{average}")
When using the for loop it seems to display a value of 64.3, which I believe is for the total of the whole student list and average for all marks.
I need to produce the an output which displays the student names and average on the same line. I can do for the names but I cannot do it for the average as I keep getting errors. I don't know what to input in.
Below is the full solution. The with open line is a context manager and ensures that the file will get closed as soon as you exit the block. You should get used to using this style as it's the safe way to do I/O. The rest is just bog standard Python.
marks=dict()
with open('studMarks.txt', 'r') as f:
for line in f:
words = line.split()
fname = words[0]
lname = words[1]
score = int(words[2])
key = f'{fname} {lname}'
count_key = f'{fname} {lname}_count'
latest_score = score + (marks.get(key)[0] if marks.get(key) else 0)
latest_count = 1 + (marks.get(key)[1] if marks.get(key) else 0)
marks[key] = (latest_score, latest_count )
for name, value in marks.items():
print(f'{name} : {value[0]/value[1]}')
This is an interesting problem.
From what I understand you have a text file that looks like this:
Johnny Ly 90 100 Adam Best 80 30 Tim Smith 10 20 in a file called studentMarks2.txt
and want output like this:
Johnny_Ly 95.0 Adam_Best 55.0 Tim_Smith 15.0
if that is true then it can be done using code like this without pandas or csv
though those would make this a lot easier.
fileContents = []
with open('studMarks2.txt','r') as f:
fileContents = f.read().split()
students = dict()
names = []
for content in fileContents:
if content.isnumeric():
studentKey = '_'.join(names)
currentScore = students.get(studentKey,[])
newScore = currentScore + [float(content)]
students.update({studentKey:newScore})
else:
if len(names) == 2:
names.clear()
names.append(content)
else:
names.append(content)
for student,scores in students.items():
avg = sum(scores)/len(scores)
print(student,avg,end=' ')
Broken down
This part reads the contents and splits on white space
fileContents = []
with open('studMarks2.txt','r') as f:
fileContents = f.read().split()
this part then iterates through the contents
storing the names as keys in a dictionary and putting the scores in a list
students = dict()
names = []
for content in fileContents:
if content.isnumeric():
studentKey = '_'.join(names)
currentScore = students.get(studentKey,[])
newScore = currentScore + [float(content)]
students.update({studentKey:newScore})
else:
if len(names) == 2:
names.clear()
names.append(content)
else:
names.append(content)
Lastly it iterates over the dictionary and output the avg on one line
for student,scores in students.items():
avg = sum(scores)/len(scores)
print(student,avg,end=' ')
I have tried multiple ways to do this but I struggle. I am new to Python trying to learn currently.
CustomerList = []
Customers = {}
Dates = {}
while True:
Customer_Name = input("Customer's Name:")
CustomerList.append(Customer_Name)
Customers_Address = input("Customer's Address:")
if Customer_Name in Customers:
Customers[Customer_Name]['Orders'] += 1
Customers[Customer_Name]['TotalAmount'] = Total_Amount
else:
Customers[Customer_Name] = {}
Customers[Customer_Name]['Address'] = Customers_Address
Customers[Customer_Name]['Orders'] = 1
Customers[Customer_Name]['TotalAmount'] = 0
file1 = open('Orders_Per_Users.txt', 'w')
file1.write(Customer_Name + " has ordered " + str(Customers[Customer_Name]['Orders']) + " times in total\n")
file1.close()
This is the output
And this is what I get exported from this output
What I want to .txt export for example is.
John has ordered 1 times in total
Mike has ordered 1 times in total
etc
etc
Opening with a 'w' tag means you are opening the file in write mode. write mode overwrites the previously existing text if any or creates a new file if the file doesnt exist.So what you might wanna do is opening it in 'a' mode (append mode) so that it doesnt overwrite the file but just appends text to it
file1 = open('Orders_Per_Users.txt', 'a')
file1.write(Customer_Name + " has ordered " + str(Customers[Customer_Name]['Orders']) + "
times in total\n")
your file permission should be append
w -
Opens in write-only mode. The pointer is placed at the beginning of
the file and this will overwrite any existing file with the same name.
It will create a new file if one with the same name doesn't exist
a -
Opens a file for appending new information to it. The pointer is
placed at the end of the file. A new file is created if one with the
same name doesn't exist. .
file1 = open('Orders_Per_Users.txt', 'a')
I hope you're enjoying your learning :)
problems are:
your code just update the text each time you add an item because of the mode of write/read operation of the file, you coded it like this:
file1 = open('Orders_Per_Users.txt', 'w')
While the correct mode is 'a' instead of 'w' to append to the file without erasing old written text!
NOTE: even if you correct it to be 'a' another issue will appear! the line will be written again in entering new order!
So what you should do is closing the file file1.close() each time you write to it in the while so your code will be looks like this:
CustomerList = []
Customers = {}
Dates = {}
while True:
Customer_Name = input("Customer's Name:")
CustomerList.append(Customer_Name)
Customers_Address = input("Customer's Address:")
if Customer_Name in Customers:
Customers[Customer_Name]['Orders'] += 1
Customers[Customer_Name]['TotalAmount'] = Total_Amount
else:
Customers[Customer_Name] = {}
Customers[Customer_Name]['Address'] = Customers_Address
Customers[Customer_Name]['Orders'] = 1
Customers[Customer_Name]['TotalAmount'] = 0
file1 = open('Orders_Per_Users.txt', 'a')
file1.write(Customer_Name + " has ordered " + str(Customers[Customer_Name]['Orders']) + " times in total\n")
file1.close()
I am writing a scoreboard thingie in python (I am fairly new to the language). Basically user inputs their name and I want the program to read the file to determine, the number that the user is assigned to.
For example, the names in the .txt file are:
Num Name Score
John Doe 3
Mitch 5
Jane 1
How do I now add user no.4 without the user typing the exact string to write, only their name.
Thanks a lot!
I suggest rethinking your design - you probably don't need the line numbers in the file, however you could just read the file and see how many lines there are.
This won't scale if you end up with a lot of data.
>>> with open("data.txt") as f:
... l = list(f)
...
This reads your header
>>> l
['Num Name Score\n', 'John Doe 3\n', 'Mitch 5\n', 'Jane 1\n']
>>> len(l)
4
So len(l)-1 is the last number, and len(l) is what you need.
the easiest way to get the number of lines is by using readlines()
x=open("scoreboard.txt", "r")
line=x.readlines()
lastlinenumber= len(line)-1
x.close()
with open('scoreboard.txt', 'a') as scoreboard: #FIle is opened for appending
username = input("Enter your name!")
scoreboard.write(str(lastlinenumber) + '. ' + str(username) + ": " + '\n')
scoreboard.close()
def add_user():
with open('scoreboard.txt', 'r') as scoreboard:
#Reads the file to get the numbering of the next player.
highest_num = 0
for line in scoreboard:
number = scoreboard.read(1)
num = 0
if number == '':
num == 1
else:
num = int(number)
if num > highest_num:
highest_num = num
highest_num += 1
with open('scoreboard.txt', 'a') as scoreboard: #FIle is opened for appending
username = input("Enter your name!")
scoreboard.write(str(highest_num) + '. ' + str(username) + ": " + '\n')
scoreboard.close()
Thank you guys, I figured it out. This is my final code for adding a new user to the list.
I'm a beginner and I have a few questions. I have a .txt file with names + grades, for example:
Emily Burgess 5 4 3 4
James Cook 4 9 5 4
Blergh Blargh 10 7 2 4
I need to write their names, last names and the average of their grades in a new .txt file. Then I need to calculate all of theirs average grade. How do I do that? I have started doing this, but I don't know what to do now:
def stuff():
things = []
file = open(r'stuff2.txt').read()
for line in file:
things.append(line.split(' '))
print(things)
for grade in things:
grades = int(grade[2], grade[3], grade[4], grade[5])
average = grades/4
print(average)
with open('newstuff.txt', 'w') as f:
f.write(things)
It's hard to tell, but it looks like you've got some problems in your for loop. For instance, you can't call the int constructor with 4 arguments:
TypeError: int() takes at most 2 arguments (4 given)
Did you mean:
grades = [int(g) for g in grades[1:]]
average = sum(grades) / len(grades[1:])
instead?
EDIT: since you're a beginning Python student, we'll leave object oriented programming out of it for now, but I'll keep the code below in case you feel like exploring a little!
students = list() # initialize an accumulator list
with open("stuff2.txt") as infile:
for line in infile:
data = line.strip().split(" ")
# strip removes ending and beginning whitespace e.g. the ending \n and etc
datadict = {}
datadict['first'] = data[0]
datadict['last'] = data[1]
datadict['grades'] = data[2:]
students.append(datadict)
# this can all be done in one line, but it's much clearer this way
# after this, all your students are in `students`, each entry in `students` is a
# dictionary with keys `first`, `last`, and `grades`.
# OUTPUT
with open("newstuff.txt","w") as outfile:
for student in students:
outputline = ""
outputline += student['first']
outputline += " "
outputline += student['last']
outputline += ": "
outputline += ", ".join(student['grades'])
# ", ".join(list) gives you a string with every element of list
# separated by a comma and a space, e.g. ','.join(["1","2","3"]) == "1, 2, 3"
outputline += "|| average: "
average = str(sum(map(int,student['grades']))/len(student['grades']))
# since student['grades'] is a list of strings, and we need to add them, you
# have to use map(int, student['grades']) to get their int representations.
# this is equivalent to [int(grade) for grade in student['grades']]
outputline += average
outputline += "\n"
outfile.write(outputline)
# again, this can be done in one line
# outfile.write("{0['first']} {0['last']}: {1}||{2}\n".format(
# student, ', '.join(student['grades']), sum(map(int,student['grades']))/len(student['grades']))
# but, again, this is long and unwieldy.
I'm always a proponent of using classes for these kinds of applications
class Student(object):
def __init__(self,name=None,grades=None,initarray=None):
"""Can be initialized as Student(name="Name",grades=[1,2,3]) or
Student(["First","Last",1,2,3])"""
if not (name and grades) or (initarray):
raise ValueError("You must supply both name and grades, or initarray")
if (name and grades):
self.name = name
self.grades = grades
else:
self.name = ' '.join(initarray[:2])
self.grades = initarray[2:]
#property
def average(self):
return sum(self.grades)/len(self.grades)
Then you can do something like:
students = list()
with open(r"stuff2.txt",'r') as f:
for line in file:
students.append(Student(line.strip().split(" ")))
# students is now a list of Student objects
And you can write them all out to a file with:
with open("students_grades.txt","w") as out_:
for student in students:
out_.write(r"{student.name}: {45:grades}||{student.average}\n".format(
student=student, grades = ', '.join(student.grades)))
Though you'll probably want to pickle your objects if you want to use them later.
import pickle
with open("testpickle.pkl","wb") as pkl:
pickle.dump(students,pkl)
Then use them again with
import pickle # if you haven't already, obviously
with open('testpickle.pkl','rb') as pkl:
students = pickle.load(pkl)
Your code can be made to work as thus:
with open('stuff2.txt') as f1, open('newstuff.txt', 'w') as f2:
for line in f:
raw_data = line.rstrip().split()
average = sum(int(i) for i in raw_data[2:])
new_data = ' '.join(raw_data[:2] + [str(average)])
f2.write(new_data)
Assuming the original txt file is stuff2.txt, and you want the output in newstuff.txt:
def process_line(line):
line = line.split()
first = line[0]
last = line[1]
grades = [int(x) for x in line[2:]]
average = sum(grades) / float(len(grades))
return first, last, average
with open('stuff2.txt') as f:
lines = f.readlines()
with open('newstuff.txt', 'w') as f:
for line in lines:
first, last, avg = process_line(line)
f.write(first + " " + last + " " + str(avg) + "\n")
Use pandas:
import pandas
df = pandas.read_csv("stuff.txt", sep=" ", header=None, names=["first","last","grade1","grade2","grade3","grade4"])
df["average"] = (df["grade1"]+df["grade2"]+df["grade3"]+df["grade4"])/4.0
df.to_csv("newstuff.txt",sep=" ", index=False) #will print a header row, which you can disable with header=None
I have a plain text file with some data in it, that I'm trying to open and read using a Python (ver 3.2) program, and trying to load that data into a data structure within the program.
Here's what my text file looks like (file is called "data.txt")
NAME: Joe Smith
CLASS: Fighter
STR: 14
DEX: 7
Here's what my program looks like:
player_name = None
player_class = None
player_STR = None
player_DEX = None
f = open("data.txt")
data = f.readlines()
for d in data:
# parse input, assign values to variables
print(d)
f.close()
My question is, how do I assign the values to the variables (something like setting player_STR = 14 within the program)?
player = {}
f = open("data.txt")
data = f.readlines()
for line in data:
# parse input, assign values to variables
key, value = line.split(":")
player[key.strip()] = value.strip()
f.close()
now the name of your player will be player['name'], and the same goes for all other properties in your file.
import re
pattern = re.compile(r'([\w]+): ([\w\s]+)')
f = open("data.txt")
v = dict(pattern.findall(f.read()))
player_name = v.get("name")
plater_class = v.get('class')
# ...
f.close()
The most direct way to do it is to assign the variables one at a time:
f = open("data.txt")
for line in f: # loop over the file directly
line = line.rstrip() # remove the trailing newline
if line.startswith('NAME: '):
player_name = line[6:]
elif line.startswith('CLASS: '):
player_class = line[7:]
elif line.startswith('STR: '):
player_strength = int(line[5:])
elif line.startswith('DEX: '):
player_dexterity = int(line[5:])
else:
raise ValueError('Unknown attribute: %r' % line)
f.close()
That said, most Python programmers would stored the values in a dictionary rather than in variables. The fields can be stripped (removing the line endings) and split with: characteristic, value = data.rstrip().split(':'). If the value should be a number instead of a string, convert it with float() or int().