Partial match in a list, from a user input - list

Trying to get a partial match in a list, from a user input.
I am trying to make a simple diagnostic program. The user inputs their ailment and the program will output a suggested treatment.
print("What is wrong with you?")
answer=input()
answer=answer.lower()
problem=""
heat=["temperature","hot"]
cold=["freezing","cold"]
if answer in heat:
problem="heat"
if answer in cold:
problem="cold"
print("you have a problem with",problem)
I can get it to pick an exact match from the list but I want it to find partial matches from my input. For example if the user types they are "too hot".

Try the code below. The key is the split() method.
answer = input('What is wrong with you?')
answer = answer.lower()
heat = ['temperature', 'hot']
cold = ['freezing', 'cold']
for word in answer.split():
if word in heat:
problem = 'heat'
if word in cold:
problem = 'cold'
print('you have a problem with', problem)

I would recommend you use something like this which might be a bit more "pythonic"
answer = input()
cold = ["freezing", "cold"]
if any(answer in c for c in cold):
problem = "cold"

Related

Scoring multiple TRUES in Pythton RE Search

Background
I have a list of "bad words" in a file called bad_words.conf, which reads as follows
(I've changed it so that it's clean for the sake of this post but in real-life they are expletives);
wrote (some )?rubbish
swore
I have a user input field which is cleaned and striped of dangerous characters before being passed as data to the following script, score.py
(for the sake of this example I've just typed in the value for data)
import re
data = 'I wrote some rubbish and swore too'
# Get list of bad words
bad_words = open("bad_words.conf", 'r')
lines = bad_words.read().split('\n')
combine = "(" + ")|(".join(lines) + ")"
#set score incase no results
score = 0
#search for bad words
if re.search(combine, data):
#add one for a hit
score += 1
#show me the score
print(str(score))
bad_words.close()
Now this finds a result and adds a score of 1, as expected, without a loop.
Question
I need to adapt this script so that I can add 1 to the score every time a line of "bad_words.conf" is found within text.
So in the instance above, data = 'I wrote some rubbish and swore too' I would like to actually score a total of 2.
1 for "wrote some rubbish" and +1 for "swore".
Thanks for the help!
Changing combine to just:
combine = "|".join(lines)
And using re.findall():
In [33]: re.findall(combine,data)
Out[33]: ['rubbish', 'swore']
The problem with having the multiple capturing groups as you originally were doing is that re.findall() will return each additional one of those as an empty string when one of the words is matched.

regex year format authentication

I have a program where the user is asked for the session year which needs to be in the form of 20XX-20XX. The constraint here is that it needs to be a year followed by its next year. Eg. 2019-2020.
For example,
Vaild Formats:
2019-2020
2018-2019
2000-2001
Invalid Fromats:
2019-2021
2000-2000
2019-2018
I am trying to validate this input using regular expressions.
My work:
import re
def add_pages(matchObject):
return "{0:0=3d}".format(int(matchObject) + 1)
try:
a = input("Enter Session")
p = r'2([0-9]{3})-2'
p1= re.compile(p)
x=add_pages(p1.findall(a)[0])
p2 = r'2([0-9]{3})-2'+x
p3 = re.compile(p2)
l=p3.findall(a)
if not l:
raise Exception
else:
print("Authenticated")
except Exception as e:
print("Enter session. Eg. 2019-2020")
Question:
So far I have not been able to retrieve a single regex that will validate this input. I did have a look at backreferencing in regex but it only solved half my query. I am looking for ways to improve this authentication process. Is there any single regex statement that will check for this constraint? Let me know if you need any more information.
Do you really need to get the session year in one input?
I think its better to have two inputs (or just automatically set the session year to be the first year + 1).
I don't know if you're aiming for something bigger and this is just an example but using regex just doesn't seem appropriate for this task to me.
For example you could do this:
print("Enter session year")
first_year = int(input("First year: "))
second_year = int(input("Second year: "))
if second_year != (first_year + 1):
# some validation
else:
# program continues
First of all, why regex? Regex is terrible at math. It would be easier to do something like:
def check_years(string):
string = "2011-2012"
years = string.split("-")
return int(years[0]) == (int(years[1]) - 1)

Python - can i recall a list name from raw_input?

I'm trying to create a game using python, but in my 'class Character:', i would like to do something like:
answer = raw_input('Which class do you want to play')
if answer = list_name[0]
self.stats = list_name
Thank you!
First note that your if statement should have an == instead of =
Also this type of situation is a great time to use python's in statement which will check if a value matches any of the items in your list! You could try something like this:
list_name = ['classA','classB','classC','classD']
answer = raw_input('Which class do you want to play: ')
#Check if the answer is one of the options in your list
if answer in list_name:
my_stats = answer
print 'great, your class is '+my_stats
else:
print 'sorry, ['+answer+'] is not an ok class'

Testing for an item in lists - Python 3

As part of a school project we are creating a trouble shooting program. I have come across a problem that I cannot solve:
begin=['physical','Physical','Software','software',]
answer=input()
if answer in begin[2:3]:
print("k")
software()
if answer in begin[0:1]:
print("hmm")
physical()
When I try to input software/Software no output is created. Can anybody see a hole in my code as it is?
In Python, slice end values are exclusive. You are slicing a smaller list than you think you are:
>>> begin=['physical','Physical','Software','software',]
>>> begin[2:3]
['Software']
>>> begin[0:1]
['physical']
Use begin[2:4] and begin[0:2] or even begin[2:] and begin[:2] to get all elements from the 3rd to the end, and from the start until the 2nd (inclusive):
>>> begin[2:]
['Software', 'software']
>>> begin[2:4]
['Software', 'software']
>>> begin[:2]
['physical', 'Physical']
>>> begin[0:2]
['physical', 'Physical']
Better yet, use str.lower() to limit the number of inputs you need to provide:
if answer.lower() == 'software':
With only one string to test, you can now put your functions in a dictionary; this gives you the option to list the various valid answers too:
options = {'software': software, 'physical': physical}
while True:
answer = input('Please enter one of the following options: {}\n'.format(
', '.join(options))
answer = answer.lower()
if answer in options:
options[answer]()
break
else:
print("Sorry, {} is not a valid option, try again".format(answer))
Your list slicing is wrong, Try the following script.
begin=['physical','Physical','Software','software',]
answer=input()
if answer in begin[2:4]:
print("k")
software()
if answer in begin[0:2]:
print("hmm")
physical()

Django Query in a loop fails for no good reason

I have this code:
msgs = int(post['time_in_weeks'])
for i in range(msgs):
tip_msg = Tip.objects.get(week_number=i)
it always results in an error saying that no values could be found.
week_number is an integer field. When I input the value of i directly,
the query works.
When i print out the value of i I get the expected values.
Any input at all would be seriously appreciated.
Thanks.
The range function will give you a zero based list of numbers up to and excluding msgs. I guess there is no Tip with week_number=0.
Also, to limit the number of queries you could do this:
for tip in Tip.objects.filter(week_number__lt=msgs):
#do something
or, if you want specific weeks:
weeks=(1,3,5)
for tip in Tip.objects.filter(week_number__in=weeks):
#do something