Sorting sentences of text file by users input - python-3.x

My code is sorting the sentences of file based on a length of the sentences by their length and saving to a new file.
How can I alter my code so that if the user inputs any number at program start, we filter the lines based on that input.
Example: The user inputs 50 - the program will sort all sentences that have a greater length than 50 or if the user inputs all then the program will sort all lines as normal.
My code:
file = open("testing_for_tools.txt", "r")
lines_ = file.readlines()
#print(lines_)
user_input = input("enter")
if user_input is int:
lines = sorted(lines_, key=len)
else:
lines = sorted(lines_, key=len)
# lines.sort()
file_out = open('testing_for_tools_sorted.txt', 'w')
file_out.write(''.join(lines)) # Write a sequence of strings to a file
file_out.close()
file.close()
print(lines)

input returns a string, always, if you want an integer or somesuch you need to parse it explicitely, you will never get an integer out of input.
is is not a type-testing primitive in python, it's an identity primitive. It checks if the left and right are the same object and that's it.
filter is what you're looking for here, or a list comprehension: if the user provided an input and that input is a valid integer, you want to filter the lines to only those above the specified length. This is a separate step from sorting.
That aside,
you should use with to manage files unless there are specific reasons that you shan't or can't
files have a writelines method which should be more efficient than writing joined lines
never ever open files in text mode without providing an encoding, otherwise Python asks the system for an encoding and it's easy for that system to be misconfigured or oddly configured leading to garbage inputs
with open("testing_for_tools.txt", "r", encoding='utf-8') as f:
lines_ = file.readlines()
#print(lines_)
user_input = input("enter")
if user_input:
try:
limit = int(user_input.strip())
except ValueError:
pass
else:
lines_ = (l for l in lines_ if len(l) >= limit)
lines = sorted(lines_, key=len)
with open('testing_for_tools_sorted.txt', 'w', encoding='utf-8') as f:
f.writelines(lines)
print(lines)

#Black Snow
I don't have anything else to answer if its working as expected.
This is a rather long answer:
idx_to_sort = [True if len(i)>int(user_input) else False for i in lines_]
idx_to_sort
lines_to_sort = []
for i in range(len(idx_to_sort)):
if idx_to_sort[i]:
lines_to_sort.append(lines_[i])
lines_to_sort
lines = sorted(lines_to_sort, key=len)
lines
counter=0
for i in range(len(idx_to_sort)):
if idx_to_sort[i]:
lines_[i] = lines[counter]
counter += 1
lines_
The output would be different but not what you expected.

Related

How can I print the line index of a specific word in a text file?

I was trying to find a way to print the biggest word from a txt file, it's size and it's line index. I managed to get the first two done but can't quite figure it out how to print the line index. Can anyone help me?
def BiggestWord():
list_words = []
with open('song.txt', 'r') as infile:
lines = infile.read().split()
for i in lines:
words = i.split()
list_words.append(max(words, key=len))
biggest_word = str(max(list_words, key=len))
print biggest_word
print len(biggest_words)
FindWord(biggest_word)
def FindWord(biggest_word):
You don't need to do another loop through your list of largest words from each line. Every for-loop increases function time and complexity, and it's better to avoid unnecessary ones when possible.
As one of the options, you can use Python's built-in function enumerate to get an index for each line from the list of lines, and instead of adding each line maximum to the list, you can compare it to the current max word.
def get_largest_word():
# Setting initial variable values
current_max_word = ''
current_max_word_length = 0
current_max_word_line = None
with open('song.txt', 'r') as infile:
lines = infile.read().splitlines()
for line_index, line in enumerate(lines):
words = line.split()
max_word_in_line = max(words, key=len)
max_word_in_line_length = len(max_word_in_line)
if max_word_in_line_length > current_max_word_length:
# updating the largest word value with a new maximum word
current_max_word = max_word_in_line
current_max_word_length = max_word_in_line_length
current_max_word_line = line_index + 1 # line number starting from 1
print(current_max_word)
print(current_max_word_length)
print(current_max_word_line)
return current_max_word, current_max_word_length, current_max_word_line
P.S.: This function doesn't suggest what to do with the line maximum words of the same length, and which of them should be chosen as absolute max. You would need to adjust the code accordingly.
P.P.S.: This example is in Python 3, so change the snippet to work in Python 2.7 if needed.
With a limited amount of info I'm working with, this is the best solution I could think of. Assuming that each line is separated by a new line, such as '\n', you could do:
def FindWord(largest_word):
with open('song.txt', 'r') as infile:
lines = infile.read().splitlines()
linecounter = 1
for i in lines:
if largest_word in lines:
return linecounter
linecounter += 1
You can use enumerate in your for to get the current line and sorted with a lambda to get the longest word:
def longest_word_from_file(filename):
list_words = []
with open(filename, 'r') as input_file:
for index, line in enumerate(input_file):
words = line.split()
list_words.append((max(words, key=len), index))
sorted_words = sorted(list_words, key=lambda x: -len(x[0]))
longest_word, line_index = sorted_words[0]
return longest_word, line_index
Are you aware that there can be:
many 'largest' words with the same length
several lines contain word(s) with the biggest length
Here is the code that finds ONE largest word and returns a LIST of numbers of lines that contain the word:
# built a dictionary:
# line_num: largest_word_in_this_line
# line_num: largest_word_in_this_line
# etc...
# !!! actually, a line can contain several largest words
list_words = {}
with open('song.txt', 'r') as infile:
for i, line in enumerate(infile.read().splitlines()):
list_words[i] = max(line.split(), key=len)
# get the largest word from values of the dictionary
# !!! there can be several different 'largest' words with the same length
largest_word = max(list_words.values(), key=len)
# get a list of numbers of lines (keys of the dictionary) that contain the largest word
lines = list(filter(lambda key: list_words[key] == largest_word, list_words))
print(lines)
If you want to get all lines that have words with the same biggest length you need to modify the last two lines in my code this way:
lines = list(filter(lambda key: len(list_words[key]) == len(largest_word), list_words))
print(lines)

Append string based on condition python

I just want to append strings based on my condition. For example all strings starting with http won't be appended but all the other strings in each that has a length of 40 will be appended.
words = []
store1 = []
disregard = ["http","gen"]
for all in glob.glob(r'MYDIR'):
with open(all, "r",encoding="utf-16") as f:
text = f.read()
lines = text.split("\n")
for each in lines:
words += each.split()
for each in words:
if len(each) == 40 and each not in disregard:
store1.append(each)
Update:
if disregard[0] not in each:
works but how can I compare it to all the contents in my list? using disregard only doesnt work
Here is my input text file :
http://1234ashajkhdajkhdajkhdjkaaaaaaad1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
genp://1234ashajkhdajkhdajkhdjkaaaaaaad1
a\a
The only thing that will append will be "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
I think the answers should depend on the number of words you want to disregard.
It's important to define what word means. If the word ends with spaces, should they all be stripped?
One solution could be to create a regular expression from all your words and use that to match the line.
import glob
import re
disregard = ["http","gen"]
pattern = "|".join([re.escape(w) for w in disregard])
for all in glob.glob(r'MYDIR/*'):
with open(all, "r", encoding="utf-16") as f:
matched_words = []
for line in f:
line = line.rstrip("\n")
if len(line) == 40 and not re.match(pattern, line):
matched_words.append(line)
print(matched_words)
The basic structure looks ok, it seems the place where it's breaking is setting up incorrect conditionals. You say you want to check where each line starts with the supplied strings, but then you split each line and check for existence of those strings. Use .startswith() instead. This will also make it so there doesn't have to be a space after "http" in order for that string to be caught.
Also, either the conditional testing should be placed after the loop that builds the words list, or else the words list should be reset at the start of each loop so you're not re-testing words you've already checked.
# adjusted some variable names for clarity
words = []
output = []
disregard = ["http","gen"]
for fname in glob.glob(r'MYDIR'):
with open(fname, "r", encoding="utf-16") as f:
text = f.read()
lines = text.split("\n")
for line in lines:
words += line.split()
for word in words:
if len(word) == 40 and not any([word.startswith(dis) for dis in disregard]):
output.append(each)

string to integer and formating code in python

I need to read from a file the number of times a letter v is mentioned. I actually know for a fact that if 'v' is in that sentence it will be the first thing to show up. The way I have it set up it goes and counts string by string and that is how it writes it, but I wan to just have one sentence mentioning the number of times 'v' is mentioned in the whole file.
f = open("triangle.txt", 'r') #opens the given name file to read input
fw = open("convert.txt",'w') #opens the given name file to write in
for line in f:
data = line.strip().split(" ")
vertices=0
vertices =(str(data.count('v')))
fw.write("Number of vertices = " + vertices +'\n')
f.close()
fw.close()
I tried
vertices += int((str(data.count('v'))))
yet that keeps giving me an error message that I can't convert string to integer.
Any suggestions greatly appreciated.
Firstly, if you want one sentence that mentions number of times 'v' is mentioned, simply write this line
fw.write("Number of vertices = " + vertices +'\n')
out of for loop. secondly,
data.count('v')
will give you an int value as output, so you don't have to first convert it to string and then back to integer. here's the amended code;
f = open("triangle.txt", 'r') #opens the given name file to read input
fw = open("convert.txt",'w') #opens the given name file to write in
vertices=0
for line in f:
data = line.strip().split(" ")
vertices += ((data.count('v')))
fw.write("Number of vertices = " + str(vertices) +'\n')
f.close()
fw.close()
Also, your code only counts 'v', if it is mentioned as an individual word in the sentence. to count the total number of times 'v' occurred, use what #bad_keypoints suggested.
If you simply want to know the number of times v was mentioned in the file, why don't you simple do this:
with open('file.dat', 'r+') as f:
v_count = f.read().count('v')

Program won't print complete words just single letters

I'm using Python and am trying to make a small game for a college assignment. I am trying to print a randomly selected word from a few external text files (with harder words in each one) and have it displayed for 2 seconds, the word then disappears and the user has to spell it. At the moment my program just displays a random letter from the text file and no whole words.
print ("""Welcome to the Spelling Game
What difficulty do you want to play?
Easy, Medium or Hard?""")
strDifficulty = input().upper
if strDifficulty is ("EASY"):
with open ('EASY.txt', 'r') as f:
(chosen) = f.readlines()
if strDifficulty is ("MEDIUM"):
with open ('MEDIUM.txt', 'r') as f:
(chosen) = f.readlines()
if strDifficulty is ("HARD"):
with open ('HARD.txt', 'r') as f:
(chosen) = f.readlines()
import random
x = ('chosen')
print (random.choice (x))
There's multiple issues with your code why it would print out a single character:
strDifficulty = input().upper does not uppercase input from the command line. It will read something you type, which is a string (str in python) and assign the method upper of that string to strDifficulty. What you're likely looking for is strDifficulty = input().upper() (the extra parentheses will call the method upper, returning an uppercased version of what is read from standard in.
x = ('chosen') is assigning the string 'chosen' to x, not the value of the variable chosen. You might have meant x = chosen, assigning the value of chosen to x.
print (random.choice(x)) isn't far off, but will choose a random element from x. As x is always the string 'chosen', you'll likely get one of those letters. You could simply remove the line x = ('chosen') and call print(random.choice(chosen)).
There's plenty more to be said about your piece of code, but let's start here :)
I have made some modifications to your code.
print ("""Welcome to the Spelling Game
What difficulty do you want to play?
Easy, Medium or Hard?""")
strDifficulty = input().upper()
if strDifficulty=="EASY":
with open ('EASY.txt', 'r') as f:
chosen = f.readlines()
if strDifficulty=="MEDIUM":
with open ('MEDIUM.txt', 'r') as f:
chosen = f.readlines()
if strDifficulty=="HARD":
with open ('HARD.txt', 'r') as f:
chosen = f.readlines()
import random
print (random.choice (chosen))

Python program for json files

i want to search a particular keyword in a .json file and print 10 lines above and below the line in which the searched keyword is present.
Note - the keyword might be present more than once in the file.
So far i have made this -
with open('loggy.json', 'r') as f:
last_lines = deque(maxlen=5)
for ln, line in enumerate(f):
if "out_of_memory" in line:
print(ln)
sys.stdout.writelines(chain(last_lines, [line], islice(f, 5)))
last_lines.append(line)
print("Next Error")
print("No More Errors")
Problem with this is - the number of times it prints the keyword containing line is equal to that number of times the keyword has been found.
it is only printing 5 lines below it, whereas i want it to print five lines above it as well.
If the json file was misused to store really a lot of information, then
processing on-the-fly may be better. In the case, keep the history lines
say in the list that is shortened if it grows above a given limit.
Then use a counter that indicates how many lines must be displayed after
observing a problem:
#!python3
def print_around_pattern(pattern, fname, numlines=10):
"""Prints the lines with the pattern from the fname text file.
The pattern is a string, numline is the number of lines printed before
and after the line with the pattern (with default value 10).
"""
history = []
cnt = 0
with open(fname, encoding='utf8') as fin:
for n, line in enumerate(fin):
history.append(line) # append the line
history = history[-numlines-1:] # keep only the tail, including last line
if pattern in line:
# Print the separator and the history lines including the pattern line.
print('\n{!r} at the line {} ----------------------------'.format(
pattern, n+1))
for h in history:
print('{:03d}: {}'.format(n-numlines, h), end='')
cnt = numlines # set the counter for the next lines
elif cnt > 0:
# The counter indicates we want to see this line.
print('{:03d}: {}'.format(n+1, line), end='')
cnt -= 1 # decrement the counter
if __name__ == '__main__':
print_around_pattern('out_of_memory', 'loggy.json')
##print_around_pattern('out_of_memory', 'loggy.json', 3) # three lines before and after

Resources