Python Spell Check With Suggestions - python

I have a program that I'm working on that takes an input and checks it to see if it spelled correctly with a dictionary inside of a file. However, I want to return a suggestion or two as well of what the person means. Any suggestions of how to do this? I have found some modules that can do it, but not for a specific dictionary from a file. Any help is appreciated!!
Here is what I have now:
def getDictionary():
theDictionary = open("theDictionary.txt", "r")
dictionaryList = []
for eachLine in theDictionary:
splitLines = eachLine.split()
dictionaryList.append(splitLines[0])
theDictionary.close()
return dictionaryList
def spellChecker(theFile, theDictionary):
lowerItems = theFile.lower()
wordList = lowerItems.split()
wrongList = []
for item in wordList:
if item not in theDictionary:
result = False
wrongList.append(item)
else:
result = True
wrongItem = ""
return (result, wrongList)
def main():
theDictionary = getDictionary()
theText = getFile()
theInput = input("Input some words here:")
result, wrongList=spellChecker(theInput,theDictionary)
if result:
print("There are no spelling errors in the sentence! Hooray!")
else:
if len(wrongList) == 1:
print('There is a spelling error in the sentence! The word that is wrong is "' + str(wrongList) + '".')
elif len(wrongList) > 1:
print('There are some spelling errors in the sentence! The words that are wrong are"' + str(wrongList) + '".')
main()

You might want to have a look at the difflib module in the Standard Library. It allows you to do approximate string matching, which seems to be what you want.
It really does not matter if your dictionary is inside a file or not, since you are loading it into a list anyway. Maybe have a look at the get_close_matches() method in the said module.

Related

Find And Replace Character In Python

For the get_letter_from_user function, while using the while loop for validation, it keeps repeating the invalid input; I want to make sure that it is a single letter and lower case, and I want to make sure that it doesn't equal the second parameter of the function. I'm not sure what I'm doing wrong, though. (and how to get gud at coding if u have tips)
def get_text_from_user(prompt):
return input(prompt).lower()
def get_letter_from_user(prompt, not_allowed):
not_allowed = ''
allowed = input(prompt).lower()
while not allowed == not_allowed or allowed.isalpha() or len(allowed) > 1:
allowed = str(input('Invalid letter, try again:'))
return allowed
def main():
text = get_text_from_user("Enter some text: ")
ltr1 = get_letter_from_user("Enter a letter: ", '')
ltr2 = get_letter_from_user("Enter another letter: ", ltr1)
new_text = text.replace(ltr1,ltr2)
print("The new text is", new_text)
if __name__ == "__main__":
main()
Suggestion for the function:
def get_letter_from_user(prompt, not_allowed):
allowed = input(prompt).lower()
while allowed == not_allowed or len(allowed) > 1:
print('not_allowed:',not_allowed)
allowed = str(input('Invalid letter, try again:'))
return allowed
ltr1 = get_letter_from_user("Enter a letter: ", '')
ltr2 = get_letter_from_user("Enter another letter: ", ltr1)
Sample output:
Enter a letter: d
Enter another letter: d
not_allowed: d
Invalid letter, try again:d
not_allowed: d
Invalid letter, try again:a
To replace a letter or sequence of letters in a string, you might want to take a look at the string.replace() function:
text = input('Enter some text: ')
find = input('Enter a letter to replace: ')
replace_with = input(f'Enter a letter to replace \'{find}\' with: ')
replaced = text.replace(find, reolace_with)
print('The new text is:', replaced)
To add another little detail because you asked how to get better at coding:
I would never make a function with a parameter that is immediately changed to an empty string. Like:
def get_letter_from_user(prompt, not_allowed):
not_allowed = ''
Rather use a default value like this:
def get_letter_from_user(prompt, not_allowed=''):
...

trying to make progrm to format chemical equation

Given an input of something like Na(Cl2)3Al(AlCl2)4 I am trying to make a program without any libraries to do this and the code that I made is not working and I cant figure out why.
can someone show me exactly where i am going wrong (or fix it for me)? the output for the example input should look like NaCl6AlAl4Cl8 where brackets are removed also. thanks in advance for any help.
def format(equation):
equation_list = list(equation)
formated = ''
for i in range(len(equation_list)):
if equation_list[i] == '(':
opening = i
if equation_list[i] == ')':
closing = i
for i in range(opening+1,closing):
if equation_list[i].isdigit():
equation_list[i] = str(int(equation_list[i])*mult)
if equation_list[i].upper():
if equation_list[i+1].isupper():
equation_list[i+1] = str(mult)
elif equation_list[i+1].isdigit():
equation_list[i+1] = str(int(equation_list[i+1])*mult)
else:
if equation_list[i+2].isupper():
equation_list[i+2] = str(mult)
elif equation_list[i+2].isdigit():
equation_list[i+2] = str(int(equation_list[i+2])*mult)
else:
if equation[i+3].isdigit():
equation_list[i+3] = str(int(equation_list[i+3])*mult)
else:
equation[i+3] = str(mult)
for i in equation_list:
formated+=i
return formated
print(format('Na(Cl2)3Al(AlCl2)4'))
As the pointed duplicate has no voted-up answered, I'd like to propose one, based on regexes. I'm pretty sure it doesn't match all cases, but yours at least
import re
EQ_PATTERN = re.compile(r"([A-Z][a-z]+\d*|\((?:[A-Z][a-z]+\d*)+\)\d*)")
BLOCK_PATTERN = re.compile(r"\(((?:[A-Z][a-z]+\d*)+)\)(\d*)")
ELEMENT_PATTERN = re.compile(r"([A-Z][a-z]+)(\d*)")
def format_element(element: str, amount: str, factor: int):
return f"{element}{int(amount or '1') * factor}"
def format_block(block: str):
if '(' not in block:
return block
inside, factor = BLOCK_PATTERN.findall(block)[0]
return "".join(format_element(element, amount, int(factor))
for element, amount in ELEMENT_PATTERN.findall(inside))
def format_equation(eq: str):
return "".join(map(format_block, EQ_PATTERN.findall(eq)))
With some tests
for eq in ('(Al3Cl2Ag6Au)4', 'Na(Cl2)3Al(AlCl2)4', 'Na2(Cl2)3Al(Al3Cl2)4'):
print(f"{eq:20s} ==> {format_equation(eq)}")
(Al3Cl2Ag6Au)4 ==> Al12Cl8Ag24Au4
Na(Cl2)3Al(AlCl2)4 ==> NaCl6AlAl4Cl8
Na2(Cl2)3Al(Al3Cl2)4 ==> Na2Cl6AlAl12Cl8

How do i replace values of a list when found in the dictionary with its key? python

so im building a simple decoder tool currently it is able to decode texting short hand expressions, like lol, to its full phrase based off of values stored in a dictionary read in from a txt file. what i would like to do is reverse this process. I would like to take the phrase laugh out loud out of the string and replace it with its abbreviation, lol. I'm new to python so my knowledge is currently limited substantially. I do know a string in immutable so i know to convert the string to a list but my issue is how do i split the string and still keep the laugh out loud together so i can run it agaisnt the dictionary. here is my code minus the txt file any ideas or comments would be greatly appreciated.
class Decry:
def __init__(self):
self.dic_usr = 0
self.decrypted = "none"
self.encrypted = "none"
self.f = 0
self.list1 = []
self.list2 = []
self.list3 = []
self.dict1 = []
self.key1 = []
self.key2 = []
self.key3 = "none"
def __buildDiction__(self):
self.f = open("dict")
self.build_list = self.f.read().splitlines()
self.d_dict = {}
for i in self.build_list:
x = i.split(",")
self.d_dict[x[0]] = x[1]
return self.d_dict
def decoder(self, usr):
self.f = self.__buildDiction__()
self.list1 = usr.split(" ")
for i in self.list1:
if i in self.f:
self.list1[self.list1.index(i)] = self.f[i]
self.decrypted = " ". join(self.list1)
return self.decrypted
def dictionary(self):
self.f = self.__buildDiction__()
self.list2 = []
self.list3 = []
self.dict1 = []
for i in self.f:
self.list3.append(i)
self.list2.append(self.f[i])
for n, g in zip(self.list3, self.list2):
self.dict1.append(n)
self.dict1.append(g)
self.key1 = [self.dict1[i:i+2] for i in range(0, len(self.dict1), 2)]
self.key2 = [" ".join(x) for x in self.key1]
self.key3 = "\n".join(self.key2)
return self.key3
def main():
print("\nWelecome to quick decrypt!!!\n"
" /~~~~~~~~~~~~~~~~~~~~~~/")
print("\n\nUse the number you desire.\n"
"Proceed at your own risk:\n"
" 1. Decrypts\n"
" 2. Read dictionary\n"
" 3. Add definitions to dictionary\n"
" 4. Quit")
deco = Decry()
option = int(input())
if option == 1:
usr_input = str(input("Enter phrase to be decoded:\n"))
f = deco.decoder(usr_input)
print(f, "\n")
return main()
if option == 2:
f = deco.dictionary()
print(f, "\n")
return main()
if option == 3:
with open("dict", "a") as txt1:
txt1.write("\n" + str(input("Enter code followed by definition with a comma no space:\n")))
return main()
if __name__ == "__main__":
main()
my issue is how do i split the string and still keep the laugh out loud together so i can run it against the dictionary
Why split the string at all? Here is a very simple solution that I hope will illustrate an alternative way to solve this without needing to split the string:
phrases = {'lol': 'laugh out loud', 'tbd': 'to be decided', 'btw': 'by the way'}
userString = "by the way here is a simple solution laugh out loud"
for abbr, phrase in phrases.items():
userString = userString.replace(phrase, abbr)
print userString
Produces:
btw here is a simple solution lol
For larger strings you may want to consider looking at regular expressions or other more efficient techniques.
As an exercise you may want to think about how string.replace works - how would you implement that function?

Nested If Expression with user validation - repeating the prompt for user input

Thank you #Idor I am making some progress but I am not 100% there yet. Right now my code looks as following:
def easy_game(easy_text, parts_of_speech1):
replaced = []
easy_text = easy_text.split()
i = 0
for word in easy_text:
replacement = word_in_pos_easy(word, parts_of_speech1)
if replacement != None:
user_input = raw_input("Type in: " + replacement + " ")
word = word.replace(replacement, user_input)
while word != solutions[i]:
print "Sorry, you are wrong"
user_input = raw_input("Type in: " + replacement + " ")
print i
i = i + 1
print i
replaced.append(word)
else:
replaced.append(word)
replaced = " ".join(replaced)
print
#time.sleep(1)
print "Ok, lets see your results. Does it make sense?"
print
#time.sleep(1)
return replaced
print
#time.sleep(1)
print easy_game(easy_text, parts_of_speech1)
You can see I added the while loop. I also added an index and for troubleshooting I added print i to see what the program is doing. It still confuses me a bit or doesn't work as I would expect it. But being a newbie to programming my expectations are probably wrong. Here's what's happening:
When you enter the correct answer the program continues to question 2 and also increases i by 1
This works from beginning to end if you enter everything correctly
When you enter the wrong answer you are prompted to enter it again. Good!
However the user then gets stuck in this very question although i has been increased to the right value.
I don't really understand why the user would be stuck at this point when i has been increased, i.e. we would check at the right position in the list for the correct answer.
This is the full code of the game. I can successfully run it on my Mac but see the above behavior. Any thoughts on this by any chance? thanks in advance!
parts_of_speech1 = ["Word1", "Word2", "Word3", "Word4"]
# The following is the text for the easy text..
easy_text = "Python is a Word1 language that provides constructs intended to enable clear programs on both small and large scale. Python implementation was started in December Word2 by Guido von Rossum. The most simple Word3 in Python is Word4 and normally used at the beginning to tell Python to write 'Hello World' on the screen."
solutions = ["programming", "1989", "function", "print"]
# Checks if a word in parts_of_speech is a substring of the word passed in.
def word_in_pos_easy(word, parts_of_speech1):
for pos in parts_of_speech1:
if pos in word:
return pos
return None
# Plays a full game of mad_libs. A player is prompted to replace words in the easy text,
# which appear in parts_of_speech with their own words.
def easy_game(easy_text, parts_of_speech1):
replaced = []
easy_text = easy_text.split()
i = 0
for word in easy_text:
replacement = word_in_pos_easy(word, parts_of_speech1)
if replacement != None:
user_input = raw_input("Type in: " + replacement + " ")
word = word.replace(replacement, user_input)
while word != solutions[i]:
print "Sorry, you are wrong"
user_input = raw_input("Type in: " + replacement + " ")
print i
i = i + 1
print i
replaced.append(word)
else:
replaced.append(word)
replaced = " ".join(replaced)
print
#time.sleep(1)
print "Ok, lets see your results. Does it make sense?"
print
#time.sleep(1)
return replaced
print
#time.sleep(1)
print easy_game(easy_text, parts_of_speech1)
I am building out a quiz based on raw_input using several different list operations. I also want to validate the user input against a list before moving on to the next question in the quiz.
The function currently looks like this:
def play_game(ml_string, parts_of_speech):
replaced = []
ml_string = ml_string.split()
for word in ml_string:
replacement = word_in_pos(word, parts_of_speech)
if replacement != None:
user_input = raw_input("Type in a: " + replacement + " ")
word = word.replace(replacement, user_input)
if word != solution_list1[0]:
print "Sorry, you are wrong. Try again!"
replaced.append(word)
else:
replaced.append(word)
replaced = " ".join(replaced)
return replaced
In Line 9 I am checking against the List containing the solution words. Whereas the validation itself works the function just continues to the next question but I need it to repeat the question until getting the correct answer. I tried to reposition the different lines but simply can't get my head around it at this point in time. Where or how do I need to place the validation of the user input correctly to prompt the user for the same question again?
It seems to me that what you are looking for is a while loop.
Instead of:
if word != solution_list1[0]:
print "Sorry, you are wrong. Try again!"
Try:
while word != solution_list1[0]:
print "Sorry, you are wrong. Try again!"
user_input = raw_input("Type in a: " + replacement + " ") # ask the user again
word = word.replace(replacement, user_input)
This way the user will have to answer the question again (raw_input) until he gets it right.

'Answered' Python what is wrong with my if statement? (raw_input)

What I want to check for is if the user input is an empty string. I want the code to execute and output: "No input", however whenever I enter no input it goes to the next if statement and executes that with a blank value.
import urllib
import re
myString = " "
i = 0
def getStockPrice():
text_file = open("data.txt", "w")
url = "http://finance.yahoo.com/q?s=" + symbolslist
htmlfile = urllib.urlopen(url)
htmltext = htmlfile.read()
regex = '<span id="yfs_l84_' + symbolslist+ '">(.+?)</span>'
pattern = re.compile(regex)
price = re.findall(pattern,htmltext)
if str(price) == myString:
print "No input"
else:
print "the price of", symbolslist," is ", price
text_file.write(str(price))
text_file.close()
dino = raw_input("What stock would you like to Check?: ")
symbolslist = dino
getStockPrice()
while i < 1000:
lilly = raw_input("What other stocks do you want to check?: ")
symbolslist = lilly
getStockPrice()
"Empty string is the one which len(String) == 0. In your case len(MyString) == 1"_wanderlust2
This gave me some insight on the issue, it was very amateurish for me to make this mistake. Thanks!
In Python, an empty string evaluates to False. That means that you can use a simple code to improve your if statement:
user_input = raw_input("Stock to check")
user_input = user_input.strip() # be sure to clear any whitespace!
if user_input:
# continue on with your program
...
If you use this Python idiom, your code will be more concise and easier to read. If you get used to it, you'll understand other Python programs that use the feature too.
For your code, I would refactor what you have to something like this:
while True:
user_input = raw_input("Stock to check")
user_input = user_input.strip() # be sure to clear any whitespace!
if user_input:
if user_input.lower() == 'quit':
break
getStockPrice(user_input)
That would rely on you changing your getStockPrice function to accept an argument though! That's a simple change. Try adding an extra word within your parentheses:
def getStockPrice(symbolslist):

Categories