I wasted plenty of hours trying to figure out the problem but no luck. Tried asking the TA at my school, but he was useless. I am a beginner and I know there are a lot of mistakes in it, so it would be great if I can get some detail explanation as well. Anyways, basically what I am trying to do with the following function is:
Use while loop to check and see if random_string is in TEXT, if not
return NoneType
if yes, then use a for loop to read lines from that TEXT and put it
in list, l1.
then, write an if statement to see if random_string is in l1.
if it is, then do some calculations.
else read the next line
Finally, return the calculations as a whole.
TEXT = open('randomfile.txt')
def random (TEXT, random_string):
while random_string in TEXT:
for lines in TEXT:
l1=TEXT.readline().rsplit()
if random_string in l1:
'''
do some calculations
'''
else:
TEXT.readline() #read next line???
return #calculations
return None
Assuming the calculation is a function of the line, then:
def my_func(fileobj,random_string,calculation_func):
return [calculation_func(line) for line in fileobj if random_string in line] or None
otherwise, you could do this:
def my_func(fileobj,random_string):
calculated = []
for line in fileobj:
if random_string in line:
#do calculations, append to calculated
return calculated or None
I omitted the while loop because it would needlessly increase the complexity of the function. fileobj assumes a file-like object, such as a buffer or like one returned by open.
Edit With while loop:
def my_func(fileobj,random_string):
calculated = []
try:
while True: #remnant from competitive programming - makes it faster
line = fileobj.readline()
if random_string in line:
#do calculations, append to calculated
except EOFError: #catches the error thrown when calling readline after file is empty.
return calculated or None
Edit 2
Taking into account the OP's new information
def my_func(fileobj,random_string):
total = 0
number = 0
try:
while True:
line = fileobj.readline()
if random_string in line:
total += float(line.split()[1])
number += 1
if total == number == 0:
return 0 #or whatever default value if random_string isn't in the file
return total/number
Shorter version:
def my_func(fileobj,random_string):
results = [float(line.split()[1]) for line in fileobj if random_string in line]
return sum(results)/len(results)
Maybe?:
def my_func(ccy):
with open('randomfile.txt', 'r') as f:
l1 = [float(line.split()[-1]) for line in f.readlines() if ccy in line]
if l1:
return sum(l1) / len(l1)
else:
return None
If I can clarify your requirements:
Use while loop to check and see if random_string is in a file, if not return None.
Collect lines that have random_string in a list.
Do some calculations on the lines collected and return the result of the calculations.
Then the following should get you started:
calculation_lines = []
random_string = 'needle'
with open('somefile.txt') as the_file:
for line in the_file:
if random_string in line:
calculation_lines.append(line)
if not calculation_lines:
return None # no lines matched
for i in calculation_lines:
# do some calculations
result_of_calculations = 42
return result_of_calculations
Related
I have started my code and am on at a very good start, however, I have come to a road block when it comes to adding sum, average, minimum, and maximum to my code, I'm sure this is a pretty easy fix to someone who knows what there are doing. Any help would be greatly appreciated. The numbers in my file are 14, 22, and -99.
Here is my code so far:
def main ():
contents=''
try:
infile = openFile()
count, sum = readFile(infile)
closeFile(infile)
display(count, sum)
except IOError:
print('Error, input file not opened properly')
except ValueError:
print('Error, data within the file is corrupt')
def openFile():
infile=open('numbers.txt', 'r')
return infile
def readFile(inf):
count = 0
sum = 0
line = inf.readline()
while line != '':
number = int(line)
sum += number
count += 1
line = inf.readline()
return count, sum
def closeFile(inF):
inF.close()
def display(count, total):
print('count = ', count)
print('Sum = ', total)
main()
In the while line!=' ': statement, it will iterate one-one single element in the file, i.e. it will add 1+4 and break the loop when we get " " according to your example. Instead, you can use .split() function and use for loop. Your code (Assuming that all numbers are in a single line):
def read_file():
f=open("numbers.txt","r")
line=f.readline()
l=[int(g) for g in line.split(",")] #there should be no gap between number and comma
s=sum(l)
avg=sum(l)/len(l)
maximum=max(l)
minimum=min(l)
f.close()
return s, avg, maximum, minimum
read_file()
Your code contains a number of antipatterns: you apparently tried to structure it OO-like but without using a class... But this:
line = inf.readline()
while line != '':
number = int(line)
sum += number
count += 1
line = inf.readline()
is the worst part and probably the culprit.
Idiomatic Python seldom use readline and just iterate the file object, but good practices recommend to strip input lines to ignore trailing blank characters:
for line in inf:
if line.strip() == '':
break
sum += number
count += 1
I am trying to create a function that takes an open file as an argument, reads the integers in the file which are all on their own line, then creates a list of those integers. The function should stop reading the file when there is an empty line. This is what I am stuck on.
def load_ints(file):
lst = []
x = 1
while x == 1:
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
x = 2
x = 2
return lst
the file I am testing it with looks like this:
1
0
-12
53
1078
Should not be read by load_ints!
len(line.strip()) != 0:
is not working,
it currently gives me a ValueError: invalid literal for int() with base 10: 'Should'
You need to put a break after the x = 2
else:
x = 2
break
Otherwise, the for loop will keep iterating over the file. It has read the blank line, executed the else condition, then carried on processing lines. So it tries to process the 'Should...' line, and fails because 'Should...' is not an integer.
Also, I don't see why you have the while statement. The for loop should be enough to iterate over the file and process each line, and the break I've suggested will exit the loop when you hit the blank line.
Other answers already point out the issue: you have to stop parsing the integers when encoutering the blank line.
Here's a one-liner using itertools.takewhile, stopping when stripping the line yields an empty line & converting to integer:
import itertools
def load_ints(file):
return [int(x) for x in itertools.takewhile(str.strip,file)]
result:
[1, 0, -12, 53, 1078]
So itertools.takewhile iterates on the file lines, and applies strip on each line. If the result is an empty string, it stops the iteration. Otherwise it continues so the line is converted to integer and added to the list comprehension.
The less lines you're writing in those cases, the less bugs you'll create with auxiliary variables & states.
I think it is not necessary the while.
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst.append(load)
else:
break
return lst
When you read a file you get a generator. Instead of reading it all to memory we could use the while loop to feed us with 1 row at a time and break when condition is met (row is blank). This should be the most efficient solution.
data = """\
1
2
-10
1241
Empty line above"""
with open("test.txt","w") as f:
f.write(data)
with open("test.txt") as f:
data = []
while True:
row = next(f).strip()
try:
data.append(int(row))
# Break if ValueError is raised (for instance blank line or string)
except ValueError:
break
data
Returns:
[1, 2, -10, 1241]
If you want a compact solution we could use takewhile from itertools. But this won't handle any error.
from itertools import takewhile
with open("test.txt") as f:
data = list(map(int,takewhile(lambda x: x.strip(), f)))
If you want to stop reading the file when the line is empty, you have to break the for loop :
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
break
return lst
You can also use re module:
import re
def load_ints(my_file):
return list(map(int, re.findall('-?\d', my_file.read())))
I just started learning Python a few weeks ago and I want to write a function which opens a file, counts and adds up the characters in each line and prints that those equal the total number of characters in the file.
For example, given a file test1.txt:
lineLengths('test1.txt')
The output should be:
15+20+23+24+0=82 (+0 optional)
This is what I have so far:
def lineLengths(filename):
f=open(filename)
lines=f.readlines()
f.close()
answer=[]
for aline in lines:
count=len(aline)
It does what I want it to do, but I don't know how to include all the of numbers added together when I have the function print.
If you only want to print the sum of the length of each line, you can do it like so:
def lineLengths(filename):
with open(filename) as f:
answer = []
for aline in f:
answer.append(len(aline))
print("%s = %s" %("+".join(str(c) for c in answer), sum(answer))
If you however also need to track lengths of all the individual lines, you can append the length for each line in your answer list by using the append method and then print the sum by using sum(answer)
Try this :
f=open(filename)
mylist = f.read().splitlines()
sum([len(i) for i in mylist])
Simple as this:
sum(map(len, open(filename)))
open(filename) returns an iterator that passes through each line, each of which is run through the len function, and the results are summed.
Once you read lines from file you can count sum using:
sum([len(aline) for aline in lines])
Separate you problem in function : a responsible by return total sum of lines and other to format sum of each line.
def read_file(file):
with open(file) as file:
lines = file.readlines()
return lines
def format_line_sum(lines):
lines_in_str = []
for line in lines:
lines_in_str.append(str(line)
return "+".join(str_lines))
def lines_length(file):
lines = read_file(file)
total_sum = 0
for line in lines:
total_sum += len(line)
return format_lines_sum(lines) + "=" + total_sum
And to use:
print(lines_length('file1.txt'))
Assuming your output is literal, something like this should work.
You can use python sum() function when you figure out how to add numbers to the list
def lineLengths(filename):
with open(filename) as f:
line_lengths = [len(l.rstrip()) for l in f]
summ = '+'.join(map(str, line_lengths)) # can only join strings
return sum(line_lengths), summ
total_chars, summ = lineLengths(filename)
print("{} = {}".format(summ, total_chars))
This should have the output you want : x+y+z=a
def lineLengths(filename):
count=[]
with open(filename) as f: #this is an easier way to open/close a file
for line in f:
count.append(len(line))
print('+'.join(str(x) for x in count) + "=" + str(sum(count))
I have a python script which print in a text file every prime.
I would like my script to pickup the list where it left off so basically take the contents of the last line as a variable.
Here is my current script:
def calc():
while True:
x = 245747
y = (100**100)**100
for n in range (x,y):
if all(n%i!=0 for i in range (2,n)):
a=[]
a.append(n)
fo = open('primes.txt', 'a+')
print(n)
print ("", file = fo)
print ((a), file = fo)
fo.close
s = input('To do another calculation input yes, to quit input anything else...')
if s == 'yes':
continue
else:
break
calc()
I would like the variable x to get as an input the last line of primes.txt
There should be on that last line "[245747]" if the greatest prime number is 245747.
How could I achieve that? Thanks!
You can do use readlines and get the last item of the list:
file = open("primes.txt", "r").readlines()
x = file[len(file)-1]
I think this should work.
You can just get rid of the 2 "[" and "]" with split or something similar.
Alright so for class we have this problem where we need to be able to input a word and from a given text file (wordlist.txt) a list will be made using any anagrams of that word found in the file.
My code so far looks like this:
def find_anagrams1(string):
"""Takes a string and returns a list of anagrams for that string from the wordlist.txt file.
string -> list"""
anagrams = []
file = open("wordlist.txt")
next = file.readline()
while next != "":
isit = is_anagram(string, next)
if isit is True:
anagrams.append(next)
next = file.readline()
file.close()
return anagrams
Every time I try to run the program it just returns an empty list, despite the fact that I know there are anagrams present. Any ideas on what's wrong?
P.S. The is_anagram function looks like this:
def is_anagram(string1, string2):
"""Takes two strings and returns True if the strings are anagrams of each other.
list,list -> string"""
a = sorted(string1)
b = sorted(string2)
if a == b:
return True
else:
return False
I am using Python 3.4
The problem is that you are using the readline function. From the documentation:
file.readline = readline(...)
readline([size]) -> next line from the file, as a string.
Retain newline. A non-negative size argument limits the maximum
number of bytes to return (an incomplete line may be returned then).
Return an empty string at EOF.
The key information here is "Retain newline". That means that if you have a file containing a list of words, one per line, each word is going to be returned with a terminal newline. So when you call:
next = file.readline()
You're not getting example, you're getting example\n, so this will never match your input string.
A simple solution is to call the strip() method on the lines read from the file:
next = file.readline().strip()
while next != "":
isit = is_anagram(string, next)
if isit is True:
anagrams.append(next)
next = file.readline().strip()
file.close()
However, there are several problems with this code. To start with, file is a terrible name for a variable, because this will mask the python file module.
Rather than repeatedly calling readline(), you're better off taking advantage of the fact that an open file is an iterator which yields the lines of the file:
words = open('wordlist.txt')
for word in words:
word = word.strip()
isit = is_anagram(string, word)
if isit:
anagrams.append(word)
words.close()
Note also here that since is_anagram returns True or False, you
don't need to compare the result to True or False (e.g., if isit
is True). You can simply use the return value on its own.
Yikes, don't use for loops:
import collections
def find_anagrams(x):
anagrams = [''.join(sorted(list(i))) for i in x]
anagrams_counts = [item for item, count in collections.Counter(anagrams).items() if count > 1]
return [i for i in x if ''.join(sorted(list(i))) in anagrams_counts]
Here's another solution, that I think is quite elegant. This runs in O(n * m) where n is the number of words and m is number of letters (or average number of letters/word).
# anagarams.py
from collections import Counter
import urllib.request
def word_hash(word):
return frozenset(Counter(word).items())
def download_word_file():
url = 'https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english-no-swears.txt'
urllib.request.urlretrieve(url, 'words.txt')
def read_word_file():
with open('words.txt') as f:
words = f.read().splitlines()
return words
if __name__ == "__main__":
# downloads a file to your working directory
download_word_file()
# reads file into memory
words = read_word_file()
d = {}
for word in words:
k = word_hash(word)
if k in d:
d[k].append(word)
else:
d[k] = [word]
# Prints the filtered results to only words with anagrams
print([x for x in d.values() if len(x) > 1])