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')
Related
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.
The code written below should give results like below. For example, if input is ' Lion head and Snake tail', output should be - 'LHAST'.
Instead the result is 'LLLLL'. Please check my code. If possible please suggest better practice and help me with better code.
Code is as follows:
#ask for Input
name = input('Input words to make acroname :')
#make all in caps
name = name.upper()
#turn them in list
listname = name.split()
#cycle through
for namee in listname:
#Get the first letter & type in same line
print(name[0],end="")
print()
input (' press a key to move out' )
You may correct your code. Instead of print(name[0]) you should use print(namee[0]) as you want to print the first letter of the word, not the original name.
A good practice is to name the variables the more descriptive you can so as to avoid such typos.
If you want to print the acronym in same line I would suggest to use below code to get variable acronym with the desired output:
phrase = raw_input('Input words to make acronym:')
phrase = phrase.upper()
list_words = phrase.split()
acronym = [word[0] for word in list_words]
acronym = "".join(acronym)
print acronym
You could use str.join with a generator-expression for a one-line solution to the problem:
>>> name = "Lion head and Snake tail"
>>> ''.join(i[0].upper() for i in name.split())
'LHAST'
why?
Well if we start from inside the generator, we are iterating through name.split(). The .split method of a str returns a list of all the different strings which have been found by splitting on what is passed into the method. The default character is a space and since we want the words, this is fine for us.
We then say that for each word i in this list, take the first character from the string with: i[0]. We then convert this to upper case with str.upper().
Then, the final step is to join all these characters together and that is done with the str.join method.
Simply:
print ''.join([P[0] for P in input('Input words to make acroname :').upper().split()])
Use input('') for python 3 and raw_input('') for python 2
To do:
Convert python to ythonpay (i.e. pick up a first letter, put it in the end and add 'ay' and make sure the user has not entered in the word numbers or alphanumeric word )
def check(word):
if word.isalnum() or word.isdigit():
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
first_letter = word[0]
new_word = word.strip(word[0])
PygLatin = new_word+first_letter+"ay"
print (PygLatin)
word= input("enter a word:").lower()
result = check(word)
result I got:
1>> enter a word -> python
2>> Enter valid word!
There are two fundamental issues with your code (and one stylistic issue).
Usually you want functions to return something. For example your intention is to take a word, move the first letter to the end of the word, and add "ay" ... in other words to render it in "Pig Latin."
But you're print-ing the results rather than return-ing them. You might think that using print returns a value (in the sense that it "returned" something to your screen or terminal). But that's not what "return" means in computer programming. The Python return statement is how your function returns a result to the rest of the program following any particular invocation of (or "call into") your function.
Here's the simplest function that would work:
def pigify(word):
return word[1:]+word[0].lower()+'ay'
... that will take a "slice" of the word from a one character offset into the string all the way to the end of the string. That's what [1:] means ... it describes a range of characters, how far to the start of the range and then how far to go to get up to (but not including) the end. Then it adds the first character (which is "zero characters" from the beginning of the string), converts that to lower case (which is harmless for all characters, and only affects capital letters) and then it adds the literal string "ay" ... and it takes all of that and returns it.
pig_latin = pigify("Python")
print(pig_latin)
# ---> prints "ythonpay"
The other issue with your code is that you're calling string methods in a confused way. word.alnum() will return True only if all the characters are alphanumeric and word.isdigit() will return True only if all of the characters are numeric. That's the same as just calling word.isdigit() since digits are a proper subset of the alphanumeric character set. In other words the only strings that will pass your code will be those which contain no letters (or other characters); clearly not what you intended.
You probably would prefer to check that the string consists entirely of alphabetic characters:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
# or else? ....
This leaves you with the question of what you should do with an invalid argument (value passed to your function's "word" parameter by the caller).
You could print an error message. But that's considered poor programming practice. You could return some special value such as Python's None value; but then code that calls your function must either check the results every time, or results can cause some other error far removed from where your function was called (where this non-string value was returned).
You can also raise an exception:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
raise ValueError("Invalid input for pigify()")
... note that I don't need to explicitly spell out else in this case; the control flow only reaches that statement if I didn't return a value, only when it's an error. Any other time the control flow returns to the calling code (the part of the program that called my pigify() function).
Another thing I could do is decide that pigify() simply returns anything that doesn't look like a "word" exactly as it was passed:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
else:
return word
... here I could just return word without the else: as it did before with the raise statement. But I personally think that looks wrong; so I've explicitly spelled out the else: clause purely for stylistic reasons.
Mostly you want your program to be composed of functions (or objects with methods) that work with (manipulate) the data, and then a smaller body of code (possibly functions or object and their methods) which then "render" the results of those manipulations. Any time you're writing a function which manipulations or transforms data and writes those results to the screen or into a web page, or out to a file or database, you should pause and reconsider your design. The transformative/manipulations and computations might be re-useable while the code which writes results is typically quite specific. So interleaving one with the other is usually a bad decision.
The str.isdigit() and str.isalnum() methods only return true if all of the characters match the criteria. Your test is written so that you want to detect whether any of the characters match the criteria:
>>> word = 'abc123'
>>> word.isdigit()
False
>>> any(map(str.isdigit, word))
True
So you can amend the code to start with something like this:
def check(word):
if not word.isalnum() or any(map(str.isdigit, word)):
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
...
FWIW, str.isalpha() would be easier to use because digits are already excluded.
In your code, you have problem with isalnum() which returns true if string contains only alphabets, only numbers or contains both alphabets and numbers so you can try to match if string only contains alphabets and execute your code as follow:
def check(word):
if word.isalpha(): # process only if word contains only alphabets
print("Thank You for Entering a valid word : {}!".format(word))
print(word[1:] + word[0] + "ay") # slicing is better choice in your case
else:
print("Enter valid word!!!")
word = input("enter a word:")
result = check(word.lower())
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!
I'm writing a program that checks if a word or sentence given by user input is a palindrome or not. This is the program so far:
def reverse(text):
a = text[::-1]
if a == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
string = str(raw_input("Enter word here:")).lower()
reverse(string)
However, this code doesn't work for sentences. So I tried to do it like this:
import string
def reverse(text):
a = text[::-1]
if a == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
notstring = str(raw_input("Enter word here:")).lower()
liststring = list(notstring)
forbiddencharacters = string.punctuation + string.whitespace
listcharacters = list(forbiddencharacters)
newlist = liststring - listcharacters
finalstring = "".join(newlist)
reverse(finalstring)
My goal is to put the punctuation and whitespace into a list and then subtracting those characters to the input of the user so that the program can tell if it's a palindrome even if the string has punctuation and/or whitespace. However, I don't know how I can subtract the elements in a list to the elements in another list. The way I did it, by creating another list that equals the user input minus the characters doesn't work (I tried it in my Xubuntu terminal emulator). Apart from that, when I run the program this error appears:
Traceback (most recent call last):
File "reverse.py", line 12, in <module>
forbiddencharacters = string.punctuation + string.whitespace
AttributeError: 'str' object has no attribute 'punctuation'
Ok so I have changed the variable name and I don't get that mistake above. Now I still don't know how to subtract the elements of the lists.
Since I'm a beginner programmer this might seem stupid to you. If that's the case, I'm sorry in advance. If anyone can solve one or both of the two problems I have, I'd be extremely grateful. Thanks in advance for your help. Sorry for bad english and long post :)
You should add some filtering along the way since palindromes have various syntax tricks (spaces, commas, etc.).
palindrome = "Rail at a liar"
def is_palindrome(text):
text = text.lower() #Avoid case issues
text = ''.join(ch for ch in text if ch.isalnum()) #Strips down everything but alphanumeric characters
return text == text[::-1]
if is_palindrome(palindrome):
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
You are on the right track, but you have used the identifier string for two different purposes.
Since you assigned to this variable name with the line:
string = str(raw_input("Enter word here:")).lower()
You can now no longer access the attributes string.punctuation and string.whitespace from the import string, because the name string is no longer bound to the module but to the user input instead.
A somewhat different approach to testing if a string is a palindrome
def palindrome(s):
s = s.lower()
ln=len(s)
for n in xrange(ln/2):
if s[n] != s[(ln-n)-1]:
return False
return True
print palindrome('Able was I ere I saw Elba')
FYI -- you'll need to tweak this to strip punctuation and white space if you like (left an an exercise to OP)
You can do that by splitting the phrase and storing it in a list. I am going to use your function (but there are more better pythonic ways to do that).
def reverse(textList1):
textList2 = textList1[::-1] #or we can use reversed(textList1)
if textList2 == text:
print "Yes, it's a palindrome."
else:
print "No, it's not a palindrome."
test1= "I am am I"
You should split the phrase and store it in a list:
test1List= test1.split(' ')
reverse(test1List)
Checking for palindrome is simple,
This works for both words and sentences.
import string
def ispalindrome(input_str):
input_str = list(input_str)
forbidden = list(string.punctuation + string.whitespace)
for forbidden_char in forbidden: # Remove all forbidden characters
while forbidden_char in input_str:
input_str.remove(forbidden_char)
return input_str == list(reversed(input_str)) # Checks if it is a palindrome
input_str = raw_input().lower() # Avoid case issues
print ispalindrome(input_str) # Get input