Detecting keywords in input - python

So I am completely new to Python. I started a week ago. I am writing a simple chatbot and have come to a point where I would like to ask an open-ended question, and if it picks up certain keywords in the input, it will print a certain response. I basically need an if command to be able to detect if a certain word is used. I hope there is some way of doing this.

To detect substrings you can use the in operator.
Example:
>>> "Hello" in "Hello World!"
True
>>> "Python" in "Hello World!"
False

There are multiple ways of doing this best solution would be to use regular expressions that way you can detect multiple keywords easily instead of having a dozen of if and elif under each other.
An example :
import re
regex_name = re.compile(r'name?$', flags=re.IGNORECASE)
regex_age = re.compile(r'age?$', flags=re.IGNORECASE)
my_input = input("Name : John")
if (regex_name.match(my_input)):
print("The string Name was found")
elif( regex_age.math(my_input)):
print("The string age was found")
else:
print("Neither Name or Age were found")

You can do it like this:
inpt = input("How are you?")
if "good" in inpt:
print("Okay you are good")
else:
print("what happend?")
The input() asks the user for input and the if statement checks for keywords of the users answer.

Related

How to integrate the .lower() function into a python script that checks for certain words?

I have a script that has a list of possible words, and an input, then checks for the words in the input but it only checks for the specific word, and I’m not sure how to integrate .lower() in it.
term = ["test1", "test2"]
raw_input = input()
if all(Variable in raw_input for Variable in term):
print("Both words were found")
else:
print("Couldn't find required words")
But I’d like to add a .lower() I've tried but can't find a way. Thanks
I hope this is what you are looking for.
term = ["test1", "test2"]
raw_input = input()
# check if all terms are in the input string including lower and upper case
if all(x.lower() in raw_input.lower() for x in term):
print("Both words were found")
else:
print("Couldn't find required words")
I assume you know that your values in term are lowercase because you define it yourself, and that the user-defined input could either be lowercase or uppercase. In this situation you can use
term = [“test1”, “test2”]
raw_input = input()
if (all(Variable in raw_input.lower() for Variable in term)):
print("Both words were found")
else:
print("Couldn't find required words")
You can apply the lower anywhere you see fit, but in this case, for performance, I added a new variable:
lower_input = raw_input.lower()
all(word in lower_input for word in terms)
Please notice that I renamed term to terms... Just to make sense in plain English.

Python check if any part of string in list

I have a list containing synonyms for the word 'Good' (this list here is shortened)
good_synonym = ['Good','good','Well','well']
And the program asks how the user is feeling
print = 'Hello, ' + name + ', How are you?'
status = raw_input('')
But sometimes, the user may respond to the question with "I am good" (or similar)
If the answer contains a word in the good synonym list, I want the program to reply
if status contains a word in good_synonym:
print ('That is good')
else:
print ('That is not so good')
note that the first line is not real python language
But I don't know which phrase to use to do the action.
Instead of a list with mixed-case words, use set objects; sets make membership testing and intersection testing much easier. Store lowercase text only, and simply lowercase the input string:
good_synonym = {'good', 'well'}
# good_synonym = set(['good', 'well']) # Python 2.6
Now test if the input string, lowercased and split on whitespace, is a disjoint set with set.isdisjoint(). If it is not a disjoint set, there is overlap between the two sets and that means at least 'good' or 'well' is present:
if not good_synonym.isdisjoint(status.lower().split()):
print ('That is good')
else:
print ('That is not so good')
Testing if a set is disjoint is efficient; it only has to test words up to the first one that is in the good_synonym set to return False quickly. You could calculate the intersection instead, but that would always test all words in the status to build a new set object.
Other solutions you may have seen, use the any() function; given a generator expression it too can be efficient as it would return True early if any of the outputs is true:
if any(word in good_synonym for word in status.lower().split()):
This, however, does all the looping and testing in Python code, while set.isdisjoint() is implemented entirely in C code.
There are many ways you could try to do this. Since you are a beginner, let's just go for something that will work - efficiency should NOT be your first consideration.
status = status.split() # breaks response into words
if any(s in good_synonyms for s in status):
print('That is good')
Of course it won't stop your program from acting as though "not good" is a reply deserving a happy answer, but this is a programming site.
Simple!
We can iterate over the good_synonyms list and check if any of them are present in the input string.
if any(synonym in status for synonym in good_synonyms):
print('That is good')
else:
print('That is not so good')
PS: To save memory, you could perhaps store the synonyms only in lower-case, as ['good', 'well'], and when you check if these are in the 'status' variable, you could just apply the .lower() on it, which just converts the entire string into lower-case, as:
good_synonyms = ['good', 'well']
if any(synonym in status.lower() for synonym in good_synonyms):
print('That is good')
Hope this helps!
Note: holdenweb's answer works too, but applying the split function on status isn't really required as you can check whether a word is present in a string(provided the words in the string are separated by a space) or not using the 'in' keyword as described above.
A short and simple solution would be to use regular expressions for pattern matching like this:
import re
line = "it is good"
good_synonyms = ["good","well"]
line = line.lower()
if any(re.search(synonym,line) for synonym in good_synonyms):
print "That is good"
else:
print "nope"
The search function of re looks for a match of pattern anywhere in the string and returns a boolean which then can be used in an if statement with any
This is a NLP question, the following code is a simple version of detecting synonym:
def is_contains_synonym(sentence, synonym):
token = sentence.split(' ')
return len(filter(lambda x: x in synonym, token)) > 0
if is_contains_synonym(status, good_synonym):
print ('That is good')
else:
print ('That is not so good')

Python : Another Name Error

I have two sets of code that essentially have the same goal but neither work and come up with the same name error. I'm trying to make it so they only letters are accept as answers, not numbers. When a number is entered as the input the program works fine but letters do not. Pleases also note that I am still new to python and am looking for basic commands if possible. I know their are many other questions like this one but none that I found answered my question. The error that comes up specifically points out the Name = input("What's your name?\n") line. Thank you in advance!
1
LetterCheck = True
while LetterCheck == True:
Name = input("What's your name?\n")
if "0" or "1" or "2" or "3" or "4" or "5" or "6" or "7" or "8" or "9" in str(Name):
print('Your name must NOT include numbers.')
else:
LetterCheck = False
print(Name)
2
LetterCheck = True
while LetterCheck == True:
Name = input("What's your name?\n")
global Name
try:
Name = int(Name)
except ValueError:
Name = str(Name)
LetterCheck = False
else:
print("Your name must NOT include numbers")
print(Name)
The Error
What's your name?
45
Your name must NOT include numbers
What's your name?
Will
Traceback (most recent call last):
File "C:/Users/Will/Documents/Python/Task 1 Debugging.py", line 3, in <module>
Name = input("What's your name?\n")
File "<string>", line 1, in <module>
NameError: name 'Will' is not defined
if "0" or "1" or "2" or "3" or "4" or "5" or "6" or "7" or "8" or "9" in str(Name):
This will always tell you there is a number in your name, because "0" is a non-zero length string and therefore truthy. Python sees if "0" or and stops there because it already knows the whole thing must be true.
What you probably want is something more like:
if any(digit in Name for digit in "0123456789"):
Or, arguably better:
if any(char.isdigit() for char in Name):
The other one where you're trying to convert the name to an integer will only succeed in the conversion if the name is all digits, not if it contains a digit. That's not what you want so you shouldn't do it that way.
You're running this in Python2. In Python2, input evaluates the user's input AS CODE. This means when you do:
>>> input("Name: ")
Name: Will
It tries to evaluate to some variable named Will. There is no such variable, so it throws a NameError. You can test this by entering "Will" (note the quotes). Now it evaluates it as a string and should work properly. But of course you could also write import os; os.listdir() and get a list of the current directory followed by what will likely be a TypeError. input is not safe in Python2.
Instead (in Python2), use raw_input.
I would just like to point out a few things:
First, "1" or "2" or "3" or "4" will evaluate "1" or "2" which is true and stop. You have to write out "1" in name or "2" in name, etc. That's highly inefficient and you should look at the posted function for has_int() as that would be a better way to implement it.
Also a name may have digits and still won't probably be parsed as an int() and raise an error so the second check is not effective at determining if a string has any numbers, only if the string is only numbers
Finally, it's not necessary but it is good practice to name your variables with lowercase letters.
Also, your name error could be because of input if you python version is not 3. Try using raw_input() if that is the case.
The goal here is to check if a string contains numbers.
if it does, ask again.
else, quit
# return true if given string does not have any numbers in them.
def has_int(s):
return any(char.isdigit() for char in s)
# ask what the name is
name = input('What is your name?')
# check if this user input has int
while has_int(name):
# if it does, re-prompt
print('Name cannot include numbers')
name = input('What is your name?')
# finally, say the name
print('Your name is {}'.format(name))
Very glad that you have decided to reach out.
I think regular expressions (python module re) (more info here: https://docs.python.org/2/library/re.html) are right up your alley. Regular expressions will allow you to determine if your string matches a "mold" or a pattern, which you can define by yourself
Regular expressions are a very broad and deep subject that take a bit of time to get used to, but I think they're absolutely worth your time. Take this introductory, friendly tutorial: http://regexone.com/
Then, in python, you can try this:
import re
input_str = raw_input(">?") #reads user input
if re.match('[0-9]+', input_str): #if the input matches the pattern "one or more numbers in the string"
print "Only letters a-z allowed!" #error out of the program
sys.exit()
The thing of importance here is the part with [0-9]+, which means "one or more numbers, any of them from 0 to 9".
Alright, I know I messed up with my previous code but to make up for it I present a working alternative, OP can refactor their program a bit like the following:
import re
while True:
input_str = raw_input("What's your name? ") #reads user input
if ( re.match('[0-9]+', input_str) ): # while the input doesn't match the pattern "one or more numbers in the string"
print "Your name must NOT include numbers." #error out of the program
else:
break
print "if you see this, the entered name fullfilled the logical condition"
Good luck!

Python - Trying to use a list value in an IF statment

I need to ask a user to input a question that will be compared to a list. The matched word will be displayed and then linked to an option menu. I have added the code below. I have managed to get the the program to search the input and return the word in the find list if a match appears. However I can not figure out how to use the result in an if statement as it is not a string value. I know there is a long way of doing this but is there a simple way of changing 'result' to a string value?
import re
question = input("Please enter your problem:")
find=["display","screen","battery"]
words=re.findall("\w+",question)
result=[x for x in find if x in words]
print (result)
if result in find:
print("Is your display not working?")
else:
print("Hard Luck")
Sorry I forgot to say that the outcome of the match will result in a different if statement being selected/printed. For example - If the 'question' used the word 'display' then an IF statement suggesting a solution will be printed, elif the 'question' used the word 'screen' then I elif for a solution to a broken screen will be printed and elif 'question' used 'battery' elif solution to charge the battery will be printed. The problem is I can not change 'result' to a str value to use in an IF statement. I can not check - if result=="display".. or if result=="screen".. or if result=="battery"...
If what you are trying to achieve is given the user input, whether any of the words in the user given by the user is also present in find list. Then you should just check whether the result list is empty or not. If the result list is empty, that means that none of the words in find were present in the list words . Example -
if result:
print("Is your display not working?")
else:
print("Hard Luck")
Please note, empty lists are considered False-like in boolean context, so you can simply do if result: , as given above.
An easier way for you to do this would be to create sets from start and use set.intersection(). Example -
import re
question = input("Please enter your problem:")
find=set(["display","screen","battery"])
words=re.findall("\w+",question)
result = find.intersection(words)
if result:
print("Is your display not working?")
else:
print("Hard Luck")
You may use set type for your task:
import re
question = input("Please enter your problem:")
find={"display","screen","battery"}
words=re.findall("\w+",question)
result=set([x for x in find if x in words])
print (result)
if result & find:
print("Is your display not working?")
else:
print("Hard Luck")
Considering you are already using a regex to extract the words from question and you considering the matched word will be displayed and then linked to an option menu you should compile the regex using the words you want to search for and do a findall with that, you also need to consider the case, if you want Screen and screen to be considered the same word you need to lower the input string:
import re
question = input("Please enter your problem:").lower()
find = ["display","screen","battery"]
r = re.compile(r"\b|\b".join(find))
words = r.findall(question)
if words:
print(words)
print("Is your display not working?")
That like your own code and all the answers here will not return a string, it potentially returns multiple strings including the same word repeated multiple times. If you want to use each word you
If you want the first match or only care if any word matches use search which will also cover is there a simple way of changing 'result' to a string value:
r = re.compile(r"|".join(find))
words = r.search(question)
if words:
print(words.group())
That will give you the first match in sentence for any word in the input sentence.
You also need to use word boundaries if you don't want to match screens etc..
find = ["display","screen","battery"]
r = re.compile(r"|".join([r"\b{}\b".format(s) for s in find]),re.I)
To do it using sets and get the actual word without a regex you can lower, split and rstrip the punctuation from each word in the sentence, then check if each word is in a set of words using next to get the first match:
from string import punctuation
question = input("Please enter your problem:").lower()
find = {"display","screen","battery"}
words = (word.rstrip(punctuation) for word in question.split())
result = next((x for x in words if word in find), None)
if result:
print(result)
print("Is your display not working?")
else:
print("Hard Luck")
Lastly if you did not actually want the words, you should not use intersection, just check if the set find is disjoint of words which will be True if any word in words appears in find:
find = {"display","screen","battery"}
words = re.findall("\w+",question)
if not find.isdisjoint(words):
print("Is your display not working?")
else:
print("Hard Luck")
If you want to output a particular message for each word, use a dict with the appropriate string for each word as the value:
import re
question = input("Please enter your problem:").lower()
find = ["display", "screen", "battery"]
r = re.compile(r"\b|\b".join(find))
output = {"screen":"screen message","display":"display message","battery":"battery message"}
word = r.search(question)
if word:
print(output[word.group()])
Or for multiple words:
output = {"screen":"screen message","display":"display message","battery":"battery message"}
words = r.findall(question)
print("\n".join([output[word] for word in words]))
import re
def questioner():
question = raw_input("Please enter your problem:")
find = ["display", "screen", "battery"]
words = re.findall("\w+", question)
result = [x for x in find if x in words]
if len(result) > 0:
print("Is your display not working?")
else:
print("Hard Luck")
if __name__ == "__main__":
questioner()
You just have to check if result list is subset of existing find list!

How to count how many words are in a text string inputted by the user in python

I was wondering if anybody could help; I'm quite new to python.
I'm currently creating a tool which analyses the text inputted by a user and shows which feedback to which list that phrase belongs to.
So far the programme is on an infinite loop and counts how many expressions have been entered all together and then how many times something has occurred in a certain list.
if text in access:
accessno +=1
counter +=1
print ('This could be classed as speech act 1: Access')
print ("number of access hits ", accessno)
print ("number of total hits ", counter)
So my question is this: how does one also get the programme to count how many words are in a sentence inputted by the user?
Any help would be much appreciated!
You can do it in the following simple way.
s = input()
# input() is a function that gets input from the user
len(s.split())
# len() checks the length of a list, s.split() splits the users input into a word list.
Links:
input()
len()
split()
Example:
>>> s = input()
"hello world"
>>> s
'hello world'
>>> s.split()
['hello', 'world']
>>> len(s.split())
2
Bonus: Do it all in one line!
print('You wrote {} words!'.format(len(input("Enter some text, I will tell you how many words you wrote!: ").split())))
name = input ()
print len(name)

Categories

Resources