i have 3 files in my folder. (pythonapp.py, numbers.txt, usednumbers.txt).
So basically my app grabs a random string from (numbers.txt) and saves it to a variable. Then it writes the variable to (usednumbers.txt). But the problem is i don't want to get any duplicate strings written to (usednumbers.txt). So i'd like my app to check whenever it grabs a new random string from (numbers.txt), that if it has been already used in the past (so if it exists in usednumbers.txt)
#imports-------------------------------
import random
#variables-----------------------------
line = random.choice(open('numbers.txt').readlines()) #get a random string
textfile = open("usednumbers.txt", "a") #open usednumbers txt file
#main----------------------------------
#here: need to check if our selected random variable "line"
#is in txt file "usednumbers.txt", if it exists there, we get a new random number
#if it doesn't exist there, we continue and write the variable there (below)
textfile.write(line) #store the number we are going to use
textfile.close() #so in future we avoid using this number again
You can modify your code little checking again and again into the file will be overkill and reading is time expensive.
So you can read number file and filter the number which are not present in usednumber and choose a random number from it.
#imports-------------------------------
import random
#variables-----------------------------
numbers = open('numbers.txt').read().splitlines() #get a random string
# alreday in usednumbes
already_in_file = set([x for x in open("usednumbers.txt", "r").read().splitlines()])
# filtering only those number swhich are not in number.txt
numbers = [x for x in numbers if x not in already_in_file]
#choose random number
if len(numbers) >0 :
line = random.choice(numbers)
#main----------------------------------
textfile = open("usednumbers.txt", "a") #open usednumbers txt file
textfile.writelines(str(line)+"\n") #store the number we are going to use
textfile.close() #so in future we avoid using this number again
You can check if the chosen line is in the lines of the text file.
#imports-------------------------------
import random
#variables-----------------------------
line = random.choice(open('numbers.txt').readlines()) #get a random string
textfile = open("usednumbers.txt", "a") #open usednumbers txt file
#main----------------------------------
#here: need to check if our selected random variable "line"
#is in txt file "usednumbers.txt", if it exists there, we get a new random number
#if it doesn't exist there, we continue and write the variable there (below)
while(line in open('usednumbers.txt').readlines()):
line = random.choice(open('numbers.txt').readlines()) #get a random string
textfile.write(line) #store the number we are going to use
textfile.close() #so in future we avoid using this number again
Update:
Not the most time performant solution.
See the solution provided by #Suryaveer Singh for a more optimized solution.
Related
i would like to generate random numbers and write them to a .txt file.
The range is : str(random.randint(0,10))
Before it generates me a random number my code should first check the .txt file. In this text file are already written down some random numbers. If the random number already exists it should generate me a new one and add it to my .txt file.
randomTxt = './random.txt'
def checkRandomNumberExists(value):
with open(randomTxt, 'a+') as random:
genRandom = str(random.randint(1,10))
if value in random:
random.write(genRandom)
random.write('\n')
I quess i am on the wrong way.
Can anyone please help me.
Thank you in advance
I don't see any reason to use argument in function because you're generating random number and you are generating random number between 1-10, what if all number is added in the text should it add number other than 1,2,3...10, please edit you question and mention that.
Below code will check if number is present in the text file or not, it will add the number in text file if it's not present else it will print the message that number already exits.
Code
import random
lines = []
num = random.randint(0,10)
f= open("random.txt","w+")
def checkRandomNumberExists():
with open("random.txt") as file:
for line in file:
line = line.strip()
lines.append(line)
if str(num) not in lines:
with open("random.txt", "a") as myfile:
myfile.write(str(num)+'\n')
print(str(num)+ ' is added in text file')
else:
print(str(num)+ ' is already exists in text file')
checkRandomNumberExists()
Output when inserted new value
7 is added in text file
Output when value is already in text file
7 is already exists in text file
Try using a while loop inside:
randomTxt = './random.txt'
with open(randomTxt, 'a+') as file:
text = file.read()
genRandom = str(random.randint(1,10))
while genRandom in text:
genRandom = str(random.randint(1,10))
file.write(genRandom)
file.write('\n')
Note: Please do not name files and variables a builtin name (i.e random) because it might override the original module.
i have successfully been able to import the text file and store it in a dictionary.i want to be able to ask the user to enter the number he wants and print the values corresponding to the number the user wants. example the file contains 2 names 1: chris 2:sam... i want the program to ask the user for an inputand the user puts in 2 it should print sam from the dictionary.
here is my code:
file = open("songranks.txt","r")
d={}
#Repeat for each song in the text file
for line in file:
#Let's split the line into an array called "fields" using the "," as a separator:
fields = line.split(",")
#and let's extract the data:
songrank = fields[0]
list =[fields[1],fields[2]]
k = [str(x) for x in list]
["".join(k)]
chris=len(k)-1
k=k[0:chris]
d[songrank]=k
#It is good practice to close the file at the end to free up resources
file.close()
Any help would be appreciated.
You have to use input() function to get user input and some changes below I suggest to make your program more compact and clear.
We should refrain from using variable name which matches the reserved keywords like list, input, and, or etc. that is why you should change variable list to some other name.
file = open("songranks.txt","r")
d={}
#Repeat for each song in the text file
for line in file:
#Let's split the line into an array called "fields" using the "," as a separator:
fields = line.split(",")
#and let's extract the data:
songrank = fields[0]
li =[fields[1],fields[2]]
k = ["".join(str(x)) for x in li][0]
d[songrank]=k
#It is good practice to close the file at the end to free up resources
file.close()
# yes indeed it is good practice
get_track_id = input("Enter track id") # Ask for input
print(d[get_track_id]) # print the track name
To get the input in python:
question = input('ask your question')
Then play with the answer stored as a string.
So from what you are saying something like:
print(d[int(question)])
I have created a text based game in python 3.3 were users pick a class for their character. I want the game to store three scores so an average can be taken. My problem is that i am unsure how to get the program to search for a name in the file and delete there oldest score, This is what the file where the scores are saved looks like:
Bennie
33
62
94
Josh
82
55
31
Jackie
10
4
3
My current code that sees if they have done the game before and if not writes there score to the file if they have i have got the code to split the lines and read them. It needs to delete the score closet to their name and insert and new score just before the next name but i am unsure how to do this. This is my current code
class_choice = input('Enter Class one, Class two or Class three.')
if class_choice == "One":
text_file = 'class1.txt'
elif class_choice == "Two":
text_file = 'class2.txt'
elif class_choice == "Three":
text_file = 'class3.txt'
else:
False
first_time = input('Is this the first you have completed this game: Yes or No?')
if first_time == 'Yes':
with open(text_file, "a") as file:
file.write("{}\n".format(name))
file.write("0\n")
file.write("0\n")
file.write("{}\n".format(score))
sys.exit()
else:
file = open(text_file, 'r')
lines = file.read().splitlines()
giving a sample python method to add a score to the file (pseudo-code) modify as needed to suit your needs (your requirement is not the most efficient method):
def add_score(user, score, text_file):
lines = text_file.splitlines()
count = len(lines)
user_exists = False
user_index = -1
num_scores = 3
user_num_scores = 0
for i in range(count-1):
line = lines[i]
if user == line:
# user previous scores start after here
user_exists = True
user_index = i
break
if not user_exists:
# user does not exist, create by appending
lines.append(user)
lines.append(str(score))
else: # user exists, fix the scores
j=1
while j <= num_scores:
line = lines[user_index+j]
j += 1
if line.isdigit():
# user score line
user_num_scores +=1
if user_num_scores == num_scores:
for i in range(1,num_scores-1): lines[user_index+i] = lines[user_index+i+1] # shift up
lines[user_index+num_scores] = str(score) # add the latest score
else: # just append/insert the score, as the previous scores are less than num_scores
lines.insert(user_index+user_num_scores, str(score))
return "\n".join(lines) # return the new text_file back
use like this:
text = file.read()
updated_text = add_score('UserName', 32, text)
Note the function given will not change the file it will just operate on the given file contents (as text_file argument). This is on purpose since if the function itself manipulated the files it would limit its use, since one can read or write the file in any convenient instant for the whole application. So this function only operates on strings. This is not the most efficient method, for example one can use a file per user and a much simpler format, but since this what is asked for this answer covers only that.
When you have finished adding scores and manipulating the files, you can update the file by writing the updated_text back to it. (Probably if the file is already opened in read mode, you will have to close it and re-open it in write mode).
To write (update) the file with the new contents use sth like this:
file.write(updated_text)
for example see here for python file I/O operations
It is not possible to change a single line inside a file. You can only append content at the end of the file or override the entire content.
If you wat to store the scores on a file, you need to read the file line by line storing each line in an auxiliar variable (concatenating lines) and when you reach the line you need to modify, concatenate the modified line into the auxiliar variable. Then keep reading the file line by line and storing it into the auxiliar variable.
When done, write down the content of the auxiliar variable in the file.
Why dont you try creating an .ini file and store your data in the attributes under sections. It's framework suits your requirements. It kind-of works like an xml file, but since your input and output parameters are limited (as you mentioned; 3 scores), it seems like the best option to opt for. Simply go through ini file manipulation using python in python docs and you will know what to do. Cheers !
My problem is that i am unsure how to get the program to search for a name in the file and delete there oldest score
I would create several .txt (or .dat) files with the name "< class >_stats[.txt]" (without the spaces, obviously). From there:
class_choice = raw_input("Choose your class")
# if needing stats
f = open("%s_stats.txt" % class_choice, "r+")
lines = f.readlines()
f.close()
stats = [float(i) for i in lines] # i.e. [3, 5.5, 4]
# rest of game
# overwrite with new stats
new_stat = get_new_stat()
f = open("%s_stats.txt" % class_choice, "w")
f.write("\n".join([str(i) for i in stats]))
However, I would recommend just keeping the stats, you may want them later, and text is cheap. Instead of reading all lines, simply open the file for appending, read the last three, and append the new stat to the end when you get your new stat, i.e.
f = open("%s_stats.txt")
lines = f.readlines[-3:] # reads last 3
f.close()
# stuff
f = open("%s_stats.txt", "a")
f.write(get_new_stat())
f.close()
I'm really new at python and needed help in making a list from data in a file. The list contains numbers on separate lines (by use of "\n" and this is something I don't want to change to CSV). The amount of numbers saved can be changed at any time because the way the data is saved to the file is as follows:
Program 1:
# creates a new file for writing
numbersFile = open('numbers.txt', 'w')
# determines how many times the loop will iterate
totalNumbers = input("How many numbers would you like to save in the file? ")
# loop to get numbers
count = 0
while count < totalNumbers:
number = input("Enter a number: ")
# writes number to file
numbersFile.write(str(number) + "\n")
count = count + 1
This is the second program that uses that data. This is the part that is messy and that I'm unsure of:
Program 2:
maxNumbers = input("How many numbers are in the file? ")
numFile = open('numbers.txt', 'r')
total = 0
count = 0
while count < maxNumbers:
total = total + numbers[count]
count = count + 1
I want to use the data gathered from program 1 to get a total in program 2. I wanted to put it in a list because the amount of numbers can vary. This is for an introduction to computer programming class, so I need a SIMPLE fix. Thank you to all who help.
Your first program is fine, although you should use raw_input() instead of input() (which also makes it unnecessary to call str() on the result).
Your second program has a small problem: You're not actually reading anything from the file. Fortunately, that's easy in Python. You can iterate over the lines in a file using
for line in numFile:
# line now contains the current line, including a trailing \n, if present
so you don't need to ask for the total of numbers in your file at all.
If you want to add the numbers, don't forget to convert the string line to an int first:
total += int(line) # shorthand for total = total + int(line)
There remains one problem (thanks #tobias_k!): The last line of the file will be empty, and int("") raises an error, so you could check that first:
for line in numFile:
if line:
total += int(line)
There's a text file that I'm reading line by line. It looks something like this:
3
3
67
46
67
3
46
Each time the program encounters a new number, it writes it to a text file. The way I'm thinking of doing this is writing the first number to the file, then looking at the second number and checking if it's already in the output file. If it isn't, it writes THAT number to the file. If it is, it skips that line to avoid repetitions and goes on to the next line. How do I do this?
Rather than searching your output file, keep a set of the numbers you've written, and only write numbers that are not in the set.
Instead of checking output file for the number if it was already written it is better to keep this information in a variable (a set or list). It will save you on disk reads.
To search a file for numbers you need to loop through each line of that file, you can do that with for line in open('input'): loop, where input is the name of your file. On each iteration line would contain one line of input file ended with end of line character '\n'.
In each iteration you should try to convert the value on that line to a number, int() function may be used. You may want to protect yourself against empty lines or non-number values with try statement.
In each iteration having the number you should check if the value you found wasn't already written to the output file by checking a set of already written numbers. If value is not in the set yet, add it and write to the output file.
#!/usr/bin/env python
numbers = set() # create a set for storing numbers that were already written
out = open('output', 'w') # open 'output' file for writing
for line in open('input'): # loop through each line of 'input' file
try:
i = int(line) # try to convert line to integer
except ValueError: # if conversion to integer fails display a warning
print "Warning: cannot convert to number string '%s'" % line.strip()
continue # skip to next line on error
if i not in numbers: # check if the number wasn't already added to the set
out.write('%d\n' % i) # write the number to the 'output' file followed by EOL
numbers.add(i) # add number to the set to mark it as already added
This example assumes that your input file contains single numbers on each line. In case of empty on incorrect line a warning will be displayed to stdout.
You could also use list in the above example, but it may be less efficient.
Instead of numbers = set() use numbers = [] and instead of numbers.add(i): numbers.append(i). The if condition stays the same.
Don't do that. Use a set() to keep track of all the numbers you have seen. It will only have one of each.
numbers = set()
for line in open("numberfile"):
numbers.add(int(line.strip()))
open("outputfile", "w").write("\n".join(str(n) for n in numbers))
Note this reads them all, then writes them all out at once. This will put them in a different order than in the original file (assuming they're integers, they will come out in ascending numeric order). If you don't want that, you can also write them as you read them, but only if they are not already in the set:
numbers = set()
with open("outfile", "w") as outfile:
for line in open("numberfile"):
number = int(line.strip())
if number not in numbers:
outfile.write(str(number) + "\n")
numbers.add(number)
Are you working with exceptionally large files? You probably don't want to try to "search" the file you're writing to for a value you just wrote. You (probably) want something more like this:
encountered = set([])
with open('file1') as fhi, open('file2', 'w') as fho:
for line in fhi:
if line not in encountered:
encountered.add(line)
fho.write(line)
If you want to scan through a file to see if it contains a number on any line, you could do something like this:
def file_contains(f, n):
with f:
for line in f:
if int(line.strip()) == n:
return True
return False
However as Ned points out in his answer, this isn't a very efficient solution; if you have to search through the file again for each line, the running time of your program will increase proportional to the square of the number of numbers.
It the number of values is not incredibly large, it would be more efficient to use a set (documentation). Sets are designed to very efficiently keep track of unordered values. For example:
with open("input_file.txt", "rt") as in_file:
with open("output_file.txt", "wt") as out_file:
encountered_numbers = set()
for line in in_file:
n = int(line.strip())
if n not in encountered_numbers:
encountered_numbers.add(n)
out_file.write(line)