I need to write a program, in Python, that looks at a list of numbers in a separate text file, and does the following: Displays all the numbers from the file, adds the total of all the numbers, tells me how many numbers are in the file. My problem is that it skips the first number in file
Here's the code for the program that's writing to the file, if that helps at all:
import random
amount = int (input ('How many random numbers do you want in the file? '))
infile = open ('random_numbers.txt', 'w')
for x in range (amount):
numbers = random.randint (1, 500)
infile.write (str (numbers) + '\n')
infile.close()
And here's my code for the reading the numbers in the file:
amount = 0
total = 0
infile = open ('random_numbers.txt', 'r')
numbers = (infile.readline())
try:
while numbers:
numbers = (infile.readline())
numbers = numbers.strip('\n')
numbers = int (numbers)
print (numbers)
total += numbers
amount += 1
except ValueError:
pass
print ('')
print ('')
amount +=1
print ('Your total is: ' ,total)
print ('The amount of numbers in file is: ', amount)
Now my issue is that it skips over the first number in the file. I first noticed it wasnt giving me the correct amount of numbers, hence the additional statement to add an additional 1 to the amount variable. But then I tested again and noticed it was skipping the first number in file.
How about:
with open('random_numbers.txt', 'r') as f:
numbers = map(lambda x: int(x.rstrip()), f.readlines())
This strips any trailing newline characters from the line in the string and then casts it as an int. It also closes the file when done with it.
I'm not sure why you'd want to count how many times it loops, but if that's what you want to do, you can do it this way:
numbers = list()
with open('random_numbers.txt', 'r') as f:
counter = 0
for line in f.readlines():
try:
numbers.append(int(line.rstrip()))
except ValueError: # Just in case line can't be converted to int
pass
counter += 1
I would just use len(numbers) with the result of the first method, though.
As ksai mentioned, the ValueError is coming up, most likely, because of the \n at the end of the line. I've added an example of catching the ValueError with a try/except just in case it comes across a line that's not convertible to a number for some reason.
Here's the code successfully running in my shell:
In [48]: import random
...:
...: amount = int (input ('How many random numbers do you want in the file?
...: '))
...: infile = open ('random_numbers.txt', 'w')
...: for x in range (amount):
...: numbers = random.randint (1, 500)
...: infile.write (str (numbers) + '\n')
...: infile.close()
...:
How many random numbers do you want in the file? 5
In [49]: with open('random_numbers.txt', 'r') as f:
...: numbers = f.readlines()
...: numbers = map(lambda x: int(x.rstrip()), numbers)
...:
In [50]: numbers
Out[50]: <map at 0x7f65f996b4e0>
In [51]: list(numbers)
Out[51]: [390, 363, 117, 441, 323]
Assuming, as in your code that generates these numbers, that the contents of 'random_numbers.txt' are integers separated by newlines:
with open('random_numbers.txt', 'r') as f:
numbers = [int(line) for line in f.readlines()]
total = sum(numbers)
numOfNums = len(numbers)
'numbers' contains all the numbers from the file in a list. You can print this or print(','.join(map(str,numbers))) if you don't want the square brackets.
'total' is their sum
'numOfNums' is how many numbers were in the file.
What ended up working for me was this:
amount = 0
total = 0
infile = open ('random_numbers.txt', 'r')
numbers = (infile.readline())
try:
while numbers:
numbers = (infile.readline())
numbers = numbers.strip('\n')
numbers = int (numbers)
print (numbers)
total += numbers
amount += 1
except ValueError:
pass
print ('')
print ('')
amount +=1
print ('Your total is: ' ,total)
print ('The amount of numbers in file is: ', amount)
Cory's tip on adding a try and except is what I believe ended up doing the trick.
If me, I would like to code like this:
from random import randint
fname = 'random_numbers.txt'
amount = int(input('How many random numbers do you want in the file? '))
with open(fname, 'w') as f:
f.write('\n'.join([str(randint(1, 500)) for _ in range(amount)]))
with open(fname) as f:
s = f.read().strip()
numbers = [int(i) for i in s.split('\n') if i.isdigit()]
print(numbers)
Or like this (need to pip install numpy):
import numpy as np
from random import randint
fname = 'random_numbers.txt'
amount = int(input('How many random numbers do you want in the file? '))
np.array([randint(1, 500) for _ in range(amount)]).tofile(fname)
numbers = np.fromfile(fname, dtype='int').tolist()
print(numbers)
I think the issue is how you placed the code as you unintentionally skipped the first row with another call of infile.readline()
amount = 0
total = 0
infile = open ('random_numbers.txt', 'r')
numbers = (infile.readline())
try:
while numbers:
numbers = numbers.strip('\n')
numbers = int (numbers)
print (numbers)
total += numbers
amount += 1
numbers = (infile.readline()) #Move the callback here.
except ValueError:
raise ValueError
print ('')
print ('')
# The amount should be correct already, no need to increment by 1.
# amount +=1
print ('Your total is: ' ,total)
print ('The amount of numbers in file is: ', amount)
Works fine for me.
Related
Write a program that prompts for a file name, then opens that file and reads through the file, looking for lines of the form:
X-DSPAM-Confidence: 0.8475
Count these lines, extract the floating point values from each of the lines, and compute the average of those values and produce an output as shown below. Do not use the sum() function or a variable named sum in your solution.*
This is my code:
fname = input("Enter a file name:",)
fh = open(fname)
count = 0
# this variable is to add together all the 0.8745's in every line
num = 0
for ln in fh:
ln = ln.rstrip()
count += 1
if not ln.startswith("X-DSPAM-Confidence: ") : continue
for num in fh:
if ln.find(float(0.8475)) == -1:
num += float(0.8475)
if not ln.find(float(0.8475)) : break
# problem: values aren't adding together and gq variable ends up being zero
gq = int(num)
jp = int(count)
avr = (gq)/(jp)
print ("Average spam confidence:",float(avr))
The problem is when I run the code it says there is an error because the value of num is zero. So I then receive this:
ZeroDivisionError: division by zero
When I change the initial value of num to None a similar problem occurs:
int() argument must be a string or a number, not 'NoneType'
This is also not accepted by the python COURSERA autograder when I put it at the top of the code:
from __future__ import division
The file name for the sample data they have given us is "mbox-short.txt". Here's a link http://www.py4e.com/code3/mbox-short.txt
I edited your code like below. I think your task is to find numbers next to X-DSPAM-Confidence:. And i used your code to identify the X-DSPAM-Confidence: line. Then I splitted the string by ':' then I took the 1st index and I converted to float.
fname = input("Enter a file name:",)
fh = open(fname)
count = 0
# this variable is to add together all the 0.8745's in every line
num = 0
for ln in fh:
ln = ln.rstrip()
if not ln.startswith("X-DSPAM-Confidence:") : continue
count+=1
num += float(ln.split(":")[1])
gq = num
jp = count
avr = (gq)/(jp)
print ("Average spam confidence:",float(avr))
Open files using with, so the file is automatically closed.
See the in-line comments.
Desired lines are in the form X-DSPAM-Confidence: 0.6961, so split them on the space.
'X-DSPAM-Confidence: 0.6961'.split(' ') creates a list with the number is at list index 1.
fname = input("Enter a file name:",)
with open(fname) as fh:
count = 0
num = 0 # collect and add each found value
for ln in fh:
ln = ln.rstrip()
if not ln.startswith("X-DSPAM-Confidence:"): # find this string or continue to next ln
continue
num += float(ln.split(' ')[1]) # split on the space and add the float
count += 1 # increment count for each matching line
avr = num / count # compute average
print(f"Average spam confidence: {avr}") # print value
Currently learning python, what I need to do is set the limit of a for loop equal to the int version of the first item read in a file
for example:
if a file contains the list:
10
1
2
3
4
...
I want the first line which contains 10, as the end limit for a for loop.
or maybe there is another way to accomplish this, that would also be appreciated.
here is what i have code:
otherFile = input("Do you have a file to open? (Y/N): ")
while(otherFile == 'Y' or otherFile == 'y'):
totalSum = 0
try:
with open(input("which file would you like to open? "), "r") as file:
for line in file:
totalSum += int(line)
print(line, end="")
print()
print("Total Sum is: ", totalSum)
except FileNotFoundError:
print("File name invalid, Please enter valid name.")
print()
except ValueError:
print("Invalid data type within file.")
otherFile = input("Do you have another file to open? (Y/N): ")
print("Goodbye")
I tried to read only the first line and turning that into an int, then setting it to limit but it did not work, i show that below:
with open(input("which file would you like to open? "), "r") as file:
numLines = int(file.readline())
for line in numLines: <---------- #what I tried
totalSum += int(line)
print(line, end="")
print()
print("Total Sum is: ", totalSum)
Do not cast string into int if you need a list you may create an integer list like this
integers="10 20 30 40"
integers = list(map(int,integers.split(" ")))
Following code can be useful for setting the limit for range
x=fh.readline()
limit_to_set=int(x.split(" ")[0])
for i in range(0,limit_to_set):
# perform your operation
# just showing what is in this file
>>> with open('file_1', 'r') as f:
... for line in f:
... print(line.rstrip())
...
2
abc
def
ghi
jkl
# print only 2 lines
>>> with open('file_1', 'r') as f:
... for _ in range(int(next(f))):
... print(next(f).rstrip())
...
abc
def
If you do it this way and there is a file where the number in the first line is greater than the total number of lines, you will have to handle the StopIteration on your own.
One way would be to write a code like this:
import pandas as pd
df = pd.read_csv('test.txt', delimiter = ' ')
num = df.columns[0]
num here is the integer you are seeking, than you can run your loop like this:
for i in range(num):
when dealing with integers you should use range()
I need to read an input file (input.txt) which contains one line of integers (13 34 14 53 56 76) and then compute the sum of the squares of each number.
This is my code:
# define main program function
def main():
print("\nThis is the last function: sum_of_squares")
print("Please include the path if the input file is not in the root directory")
fname = input("Please enter a filename : ")
sum_of_squares(fname)
def sum_of_squares(fname):
infile = open(fname, 'r')
sum2 = 0
for items in infile.readlines():
items = int(items)
sum2 += items**2
print("The sum of the squares is:", sum2)
infile.close()
# execute main program function
main()
If each number is on its own line, it works fine.
But, I can't figure out how to do it when all the numbers are on one line separated by a space. In that case, I receive the error: ValueError: invalid literal for int() with base 10: '13 34 14 53 56 76'
You can use file.read() to get a string and then use str.split to split by whitespace.
You'll need to convert each number from a string to an int first and then use the built in sum function to calculate the sum.
As an aside, you should use the with statement to open and close your file for you:
def sum_of_squares(fname):
with open(fname, 'r') as myFile: # This closes the file for you when you are done
contents = myFile.read()
sumOfSquares = sum(int(i)**2 for i in contents.split())
print("The sum of the squares is: ", sumOfSquares)
Output:
The sum of the squares is: 13242
You are trying to turn a string with spaces in it, into an integer.
What you want to do is use the split method (here, it would be items.split(' '), that will return a list of strings, containing numbers, without any space this time. You will then iterate through this list, convert each element to an int as you are already trying to do.
I believe you will find what to do next. :)
Here is a short code example, with more pythonic methods to achieve what you are trying to do.
# The `with` statement is the proper way to open a file.
# It opens the file, and closes it accordingly when you leave it.
with open('foo.txt', 'r') as file:
# You can directly iterate your lines through the file.
for line in file:
# You want a new sum number for each line.
sum_2 = 0
# Creating your list of numbers from your string.
lineNumbers = line.split(' ')
for number in lineNumbers:
# Casting EACH number that is still a string to an integer...
sum_2 += int(number) ** 2
print 'For this line, the sum of the squares is {}.'.format(sum_2)
You could try splitting your items on space using the split() function.
From the doc: For example, ' 1 2 3 '.split() returns ['1', '2', '3'].
def sum_of_squares(fname):
infile = open(fname, 'r')
sum2 = 0
for items in infile.readlines():
sum2 = sum(int(i)**2 for i in items.split())
print("The sum of the squares is:", sum2)
infile.close()
Just keep it really simple, no need for anything complicated. Here is a commented step by step solution:
def sum_of_squares(filename):
# create a summing variable
sum_squares = 0
# open file
with open(filename) as file:
# loop over each line in file
for line in file.readlines():
# create a list of strings splitted by whitespace
numbers = line.split()
# loop over potential numbers
for number in numbers:
# check if string is a number
if number.isdigit():
# add square to accumulated sum
sum_squares += int(number) ** 2
# when we reach here, we're done, and exit the function
return sum_squares
print("The sum of the squares is:", sum_of_squares("numbers.txt"))
Which outputs:
The sum of the squares is: 13242
fname = input("Enter file name: ")
count=0
fh = open(fname)
for line in fh:
if not line.startswith("X-DSPAM-Confidence:") : continue
count=count+1
halo=line.find("0")
gh=line[halo:]
tg=gh.rstrip()
ha=float(tg)
total=0
for value in range(ha):
total=total+value
print total
its like a list of decimal number in file ok
0.1235
0.1236
0.1678
I convert it into float where 'tg' have not an array like a list
ha=float(tg)
total=0
for value in range(ha):
total=total+value
print total
error: start must be an integer
I know it's a mistake of using range what should I use instead of range?
If you want to get a sum of floats, just use the code:
fname = input("Enter file name: ")
count = 0
total = 0
fh = open(fname)
for line in fh:
if not line.startswith("X-DSPAM-Confidence:"): continue
count += 1
halo = line.find("0")
gh = line[halo:]
tg = gh.rstrip()
ha = float(tg)
total += ha
print total
You are passing a float as argument to range, which does not make sense. range returns a list with n elements when n is the only argument of range. For example:
>>> range(3)
[0, 1, 2]
So you can see that range of a float does not make sense.
If I understand your code correctly, I think you want to replace:
for value in range(ha):
total=total+value
By
total += ha
On a separate note, and trying not to be too pedantic, I am pretty impressed by how many principles of PEP 8 your code violates. You may think it's not a big deal, but if you care, I would suggest you read it (https://www.python.org/dev/peps/pep-0008/)
def make_number_list(a_file):
number_list= []
for line_str in a_file:
line_list = line_str.split()
for number in line_list:
if number != " ":
number_list.append(number)
return number_list
opened_file = open(input("Name of input file: "))
a_file_list = make_number_list(opened_file)
print(a_file_list)
print("Length: ", len(a_file_list))
I am trying to read (eventually) 1000 integer values from a file into a list.. then find their max, min and i th value. However, this is not working to read the list (I'm just using a test list which is a file in TextEdit and is a bunch of random numbers separated by a single white space). Any suggestions?
# assumes Python 3.x
def read_nums(fname):
with open(fname) as inf:
return [int(i) for i in inf.read().split()]
def main():
fname = input("Name of input file: ")
nums = read_nums(fname)
print("Read {} numbers".format(len(nums)))
if __name__=="__main__":
main()
I am not sure how the numbers are present in your input file. Nonetheless, there are a few changes you could do to your code:
Move the return statement outside the loop.
A better way of checking if number exists would be:
if number.isdigit():
Which gives you:
def make_number_list(a_file):
number_list= []
for line_str in a_file:
line_list = line_str.split()
for number in line_list:
if number.isdigit():
number_list.append(number)
return number_list