Checking if string contains values of nested lists - python - python

First of all, do you know why this code doesn't work at all? When I give it the input 'when was steve jobs born' it returns nothing. Secondly I'm almost certain this can be written in a more efficent way which would take less time for the program to execute. Any ideas? Thanks!
import sys
Bill_Gates = ["bill gates","1955", "Co-founder of Microsoft"]
Steve_Jobs = ["steve jobs","1955", "Co-Founder of Apple"]
Albert_Einstein = ["albert einstein","1879", "Phycisist"]
PEOPLE = [Bill_Gates, Steve_Jobs, Albert_Einstein]
userInput = input("say something")
#checking if userInput contains the peoples name
if userInput in [j for i in PEOPLE for j in i]:
for i in range(len(PEOPLE)):
if PEOPLE [i][0] in userInput:
if "when was" in userInput:
if "born" in userInput:
print(PEOPLE[i][0] + "was born in " + PEOPLE[i][1])
UPDATE:
Ahsanul Haque gave me just the answer I was searching for.

You should try to debug these kinds of problems yourself by breaking down what happens at each step. Printing the variables at each stage or playing around with a shell or debugger such as pdb are very helpful. In this case:
>>> Bill_Gates = ["bill gates","1955", "Co-founder of Microsoft"]
>>> Steve_Jobs = ["steve jobs","1955", "Co-Founder of Apple"]
>>> Albert_Einstein = ["albert einstein","1879", "Phycisist"]
>>>
>>> PEOPLE = [Bill_Gates, Steve_Jobs, Albert_Einstein]
>>> things = [j for i in PEOPLE for j in i]
>>> things
['bill gates', '1955', 'Co-founder of Microsoft', 'steve jobs', '1955', 'Co-Founder of Apple', 'albert einstein', '1879', 'Phycisist']
>>> 'steve jobs' in things
True
>>> 'when was steve jobs born' in things
False
So the if userInput in [j for i in PEOPLE for j in i] fails because the right hand side is just a list of strings and Python isn't magic.
Your code is almost there anyway, as it works without the initial check. So this works:
for person in PEOPLE:
if person[0] in userInput and "when was" in userInput and "born" in userInput:
print(person[0] + " was born in " + person[1])
Note that a direct for loop works in this situation; there is no need to use range and index manually. Using the and operator is also cleaner than nested if statements.
This is plenty efficient as is unless PEOPLE has some tens of millions of elements. If you get to that stage you can look into search engine indexing techniques.

'when was steve jobs born' isn't in that list you made, whatever it is; since the outer if fails, nothing inside it gets executed.

What about making a Person class? It's simple, readable and easy to manage.
For example, I've written a Person class with a get_role method. Write your own get_name() and get_year_of_birth method.
class Person:
def __init__(self, name, year_of_birth, role):
self.name = name
self.year_of_birth = year_of_birth
self.role = role
def get_role(self):
return self.role
Bill_Gates = Person("bill gates","1955", "Co-founder of Microsoft")
Steve_Jobs = Person("steve jobs","1955", "Co-Founder of Apple")
Albert_Einstein = Person("albert einstein","1879", "Phycisist")
person_list= [Bill_Gates,Steve_Jobs,Albert_Einstein]
for person in person_list:
print person.get_role()
Output:
Co-founder of Microsoft
Co-Founder of Apple
Phycisist

Related

Concatenate random element from list with user input in Python

I'm writing a code that allows a user to enter a city they have been to. After the user inputs it, I want my code to return a randomly generated remark about the city from my list. However, whenever I run the code, it concatenates the user input with a random letter, which is not my intention of the code.
import random
message = "Type your city here: "
#Comments to concatenate with user input
comments = [f"what a lovely {}", f"I always wanted to visit {}", "I hope you enjoyed your trip to {}"]
#While loop for user input
while True:
message = input(message)
for elem in comments:
message += random.choice(elem)
if message == "quit":
break
I assume this is what your looking for?
import random
#Comments to concatenate with user input
comments = ["what a lovely ", "I always wanted to visit ", "I hope you enjoyed your trip to "]
#While loop for user input
message = None
while message != "quit":
message = input("Type your city here: ")
print(random.choice(comments)+message)
I recommend coding a function that takes the city as input then at the end returns the list. Like this
def random_quote(city):
comments = [f"what a lovely ", f"I always wanted to visit ", "I hope you
enjoyed your trip to "]
comment = random.choice(comments)
return comment + city
random.choice() accepts a list (take a look at the docs), Don't iterate over your comments variable, pass it to random.choice() and don't forget to replace {} with the city:
city = input('Please enter a city')
comment = random.choice(comments)
comment.replace('{}', city)
print(comment)
You do not need a for loop inside your while. You should always avoid while True as it is an opening for bugs. Having a break inside a loop usually marks bad programming.
You should probably read a bit about what f-string is before using it, you also don't seem to know what random.choice does since you put it into the for which gave it the messages, which it randomly took a character out of.
import random
def main():
prompt = "Type your city here: "
# Comments to concatenate with user input
comments = ["what a lovely ", "I always wanted to visit ", "I hope you enjoyed your trip to "]
usr_input = input(prompt)
# While loop for user input
while usr_input != 'quit':
message = random.choice(comments) + usr_input
usr_input = input(prompt)
if __name__ == '__main__':
main()

Python: check if a dictionary item is in string, then return the match

I have a database table that looks like the following:
id phrases message
1 "social media, marketing" "This person is in marketing!"
2 "finance, fintech "This person is in finance!"
I've looped through the key phrases and added them to a dictionary, like so:
messages = self.db_access.execute("SELECT * FROM messages")
messages = self.db_access.fetchall()
print(len(messages))
if self.db_access.rowcount > 0:
has_message = True
phrase_list = {}
for the_rule in messages:
print(the_rule[1])
rule = the_rule[1].split(',')
for phrase in rule:
phrase = str(phrase)
phrase_list[phrase] = str(the_rule[2])
print(phrase_list)
print("\n")
else:
has_message = False
This then produces the following:
# phrase_list
{'social media': 'This person is in marketing!',
'marketing': 'This person is in marketing!',
'finance': 'This person is in finance!',
'fintech': 'This person is in finance!'}
So, each phrase has it's own accompanying message, which is used elsewhere.
Now, I can compare those dict keys against a string, like so:
descriptions = ["I am in marketing, and it is super awesome", "I am in finance, and it is super awesome"]
My next step is to compare that string with the keys, and if it contains any of the keywords, then print the matching key and its value/message. This is what I have so far:
for description in descriptions:
print(description)
if has_message == True:
if any(x in description for x in phrase_list):
# print matching keyword and message
else:
print("No matches, but a phrase list exists")
So my question is, what do I need to replace that comment with to output 1) the keyword it matched with, and 2) the message associated with that keyword?
You just have to restructure your code a bit. The need for that arouses from the use of any which does not return information on which x made the expression evaluate as True. It just tells you that someone did or that noone did. If you do care about which one you have to loop through or possibly use next. Anyway, here is one way to do it:
for description in descriptions:
print(description)
if has_message == True:
for x in phrase_list:
if x in description:
print(x, phrase_list[x])
break
else:
print("No matches, but a phrase list exists")
Note:
if the else on the for is confusing, just remove it. The code will reach it only if the x is not in any description anyway.
Might want to tweak it a bit, but you can use a regular expression to search for a matching key, then look that back up in your dictionary, eg:
import re
phrase_list = {'social media': 'This person is in marketing!',
'marketing': 'This person is in marketing!',
'finance': 'This person is in finance!',
'fintech': 'This person is in finance!'}
descriptions = ["I am in marketing, and it is super awesome", "I am in finance, and it is super awesome", 'john smith']
def find_department(lookup, text):
m = re.search('|'.join(sorted(lookup, key=len, reverse=True)), text)
if m:
return lookup[m.group(0)]
else:
return 'This person is a mystery!'
Then running this gives you:
for desc in descriptions:
print(desc, '->', find_department(phrase_list, desc))
#I am in marketing, and it is super awesome -> This person is in marketing!
#I am in finance, and it is super awesome -> This person is in finance!
#john smith -> This person is a mystery!

How to use a function's if statement to use info from another function?

So I'm designing a sign-in AI, and I want it to work so that the admin name is Shawn. Here is my issue:
The program starts with the interface -
def interface():
username = input('Hello traveler, what is your name? ')
lowerUsername = username.lower()
print()
print()
if lowerUsername == 'megan':
print()
print('So you are the one Shawn has told me so much about? You are looking beautiful today my dear ☺️🌷')
elif lowerUsername == 'shawn':
OfficialSignInEdit()
So you can see at the end that if the user inputs that their name is 'shawn' at sign-in, it calls on the OfficialSignInEdit function, which is the admin sign in. It looks like this:
def OfficialSignInEdit():
print()
if PossInputs('perio', 'What street did you grow up on?: ') == correct:
print()
print('Greetings Master Shawn, it is a pleasure to see you again πŸ™‚')
else:
print()
res1 = input('Incorrect password, try again? (Yes/No)')
lowres1 = res1.lower()
if lowres1 == 'yes':
print()
print()
OfficialSignIn()
elif lowres1 == 'no':
print()
print()
interface()
So I have pinpointed the source of my issue to be right here in this particular line:
if PossInputs('perio', 'What street did you grow up on?: ') == correct:
print()
print('Greetings Master Shawn, it is a pleasure to see you again πŸ™‚')
this (just for your reference) is the PossInputs function:
def PossInputs(x, y):
term = x
question = input(y)
lowQuestion = question.lower()
words = lowQuestion.split()
if term in words:
print()
print (correct)
else:
print()
print (incorrect)
So what I want to happen is, when 'shawn' is entered as a name, the program will jump to the OfficialSignInEdit Function, and ask the question 'What street did you grow up on?'. Then IF the user enters the answer 'perio', the program will print 'correct', and then print the message 'Greetings Master Shawn, it is a pleasure to see you again'. I tried to say that IF PossInputs == correct (and I did define correct = 'correct', and incorrect = 'incorrect' outside all functions) then this would happen, but instead it prints 'correct', and then 'Incorrect password, try again? (Yes/No)', so how can I make a conditional statement that says that if the user answers 'perio', then it will print the welcome message?
Just for thoroughness sake, I also tried
if PossInputs('perio', 'What street did you grow up on?: ') == True
also without success...
anyways anything you can give me is extremely appreciated, if you have any questions or you would like to to clarify something about the written code, I would be more than happy to get back with you as soon as I can.
Thanks!

What can you use instead of zip?

Soooo, this is killing me right now. Should've asked a lot earlier, but there we go. So I think there is something wrong with the zip that I've made, and it's driving me mad. If there's an another way to do this, please let me konw, but if you teach me how to use zip, that'll be great to. Also if someone can point out all the things I've messed up, that would be fantastic.
fun_string = """In ___0___, crazy ___1___ with ___2___, ate a meal called ___3___ on a grill""",
horror_string = """In ___0___ owned by ___1___, many were killed by ___2___ because of huanted ___3___""",
mystery_string = """The most mysterious place on Earth is ___0___, next to ___1___'s house because of a ___2___ living in ___3___"""
answers = [ ]
blanks = ["___0___", "___1___", "___2___", "___3___"]
def select_level():
user_input = raw_input("""Type in a story you wish to play: """)
while user_input not in ["Fun","Horror","Mystery"]:
user_input = raw_input("Invalid story. Please try again: ")
if user_input == "Fun":
quiz(fun_string, answers, blanks)
if user_input == "Horror":
quiz(horror_string, answers, blanks)
if user_input == "Mystery":
quiz(mystery_string, answers, blanks)
def zip(*iterables):
# zip('ABCD', 'xy') --> Ax By
iterables = map(iter, iterables)
while iterables:
yield tuple(map(next, iterables))
def quiz(quiz_string, answers, blanks):
print quiz_string
for answer, question in zip(answers, blanks):
raw_input ("Type in a word: ")
quiz_string = quiz_string.replace(blanks[1], answers)
if blanks == None:
print quiz_string
print """Welcome to kis ReMadlibs!!!!"""
print """Select a story you wish to particiate!!"""
print """Fun, Horror, Mystery"""
print select_level()
It's not clear why you're using your own zip() instead of Python's zip(), nor why you believe you need zip() at all. You can get this program to work by simplifying the code:
fun_string = """In ___0___, crazy ___1___ with ___2___, ate a meal called ___3___ on a grill"""
horror_string = """In ___0___ owned by ___1___, many were killed by ___2___ because of huanted ___3___"""
mystery_string = """The most mysterious place on Earth is ___0___, next to ___1___'s house because of a ___2___ living in ___3___"""
answers = []
blanks = ["___0___", "___1___", "___2___", "___3___"]
def select_level():
user_input = raw_input("Type in a story you wish to play: ")
while user_input not in ["Fun", "Horror", "Mystery"]:
user_input = raw_input("Invalid story. Please try again: ")
if user_input == "Fun":
quiz(fun_string, answers, blanks)
elif user_input == "Horror":
quiz(horror_string, answers, blanks)
elif user_input == "Mystery":
quiz(mystery_string, answers, blanks)
def quiz(quiz_string, answers, blanks):
print quiz_string
for blank in blanks:
answer = raw_input("Type in a word: ")
quiz_string = quiz_string.replace(blank, answer)
answers.append(answer)
print quiz_string
print """Welcome to kis ReMadlibs!!!!"""
print """Select a story you wish to particiate!!"""
print """Fun, Horror, Mystery"""
select_level()

Why does it say Global Name not Defined when it is? Python [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am scripting a very simple guess the animal game where the player does the guessing. I have taken a long time to imput all the information and I know that it is very long-winded and could probably be done in much shorter ways but I am a beginner. The thing is, part of it is not working. I will put the code in and highlight the areas that arn't working and explain what happens....
def animalmenu():
print()
print()
print('Welcome to the menu. I am thinking of an animal. Select the option\'s below to try and guess my animal.')
print()
print('a) No. of Legs')
print('b) Type of animal')
print('c) Preffered Climate')
print('d) Size')
print('e) Colour')
print('f) Diet')
print('g) Habitat')
print('h) Can be kept as pet')
print('i) Guess the animal')
print()
AniChoice = input('Choose your option: ')
if AniChoice == 'a':
choicea()
if AniChoice == 'b':
choiceb()
if AniChoice == 'c':
choicec()
if AniChoice == 'd':
choiced()
if AniChoice == 'e':
choicee()
elif AniChoice == 'f':
choicef()
elif AniChoice == 'g':
choiceg()
elif AniChoice == 'h':
choiceh()
elif AniChoice == 'i':
guessing()
So that is the basic lay out of the menu. Then for each option there is a sub-menu, for example:
def choicea():
print()
print('')
print()
guessleg = input('Guess the number of legs (insects may be listed as \'lots\': ')
if leg == guessleg:
print('True')
print('r = Return to menu, g = guess again.')
elif leg != guessleg:
print('False')
print('r = Return to menu, g = guess again.')
These sub-menu's work fine till you get to sub-menu's f to i... I don't know what is wrong. You get the data that you are trying to guess from another area of the code which goes like this...
def animalchoice():
asdf = ('dog', 'monkey', 'parrot', 'fox', 'mouse', 'lady-bird', 'badger', 'shark', 'whale', 'pigeon')
from random import choice
animal = choice(asdf)
if animal == 'dog':
leg = '4'
breed = 'mammal'
climate = 'any'
size = 'dog+'
colour = 'depends'
diet = 'a'
habitat = 'ground'
pet = 'yes'
if animal == 'monkey':
leg = '4'
breed = 'mammal'
climate = 'hot'
size = 'dog+'
colour = 'brown'
diet = 'c'
habitat = 'tree'
pet = 'no'
this continues for more animals. When I run the script, it works fine. I have added loops etc. in different places and it's fine. But when I try and run say option g from the menu (def choiceg) it comes up with all sorts of errors, basically saying that the global name'habitat' (the thing we're trying to guess in that particular area) is not defined. I have coded those areas in the same way as the other areas and yet it won't work... what am I doing wrong? aside from the long winded way of scripting....
Help!?!?! How do I prevent the errors???
When you define those variables, you're setting them within those functions. They're not actually global variables at all. Your main choices are to
configure them as global variables,
create "state" objects to pass around (like setting data['habitat'] = 'tree' and returning that from the animalchoice function),
put the functions inside a class and store your values as class variables, like:
class GuessingGame(object):
[...]
def animalchoice(self):
asdf = ('dog', 'monkey', 'parrot', 'fox', 'mouse', 'lady-bird', 'badger', 'shark', 'whale', 'pigeon')
from random import choice
animal = choice(asdf)
if animal == 'dog':
self.leg = '4'
self.breed = 'mammal'
self.climate = 'any'
self.size = 'dog+'
I can't tell you which one is "best" because that will depend on how you want to structure the rest of your program.
Besides the other answers, you can restructure your code to something like:
from random import choice
data = {
"dog": dict(
leg = '4',
breed = 'mammal',
climate = 'any',
size = 'dog+',
colour = 'depends',
diet = 'a',
habitat = 'ground',
pet = 'yes',
),
"monkey": dict(
leg = '4',
breed = 'mammal',
climate = 'hot',
size = 'dog+',
colour = 'brown',
diet = 'c',
habitat = 'tree',
pet = 'no',
),
# <<Add animals here>> ....
}
data["animal"] = data[choice(data.keys())] # Current random animal
def animalmenu():
choices = {
"a": ("No. of Legs", "leg"),
"b": ("Type of animal", "breed"),
"c": ("Preffered Climate", "climate"),
"d": ("Size", "size"),
"e": ("Colour", "colour"),
# <<add attributes here>>...
}
while True:
for k, v in choices.items():
print "%s) %s" % (k, v[0])
option = raw_input('Choose your option: ')
if not option:
break
if option in choices:
guess_attr(choices[option][0], choices[option][1])
print
def guess_attr(caption, attr):
global data
while True:
guess = str(raw_input('Guess the %s :' % caption))
ok = guess==str(data["animal"][attr])
print ok
if ok:
break
option = raw_input('r = Return to menu, g = guess again: ')
if option=="r":
break
print
animalmenu()
This way, you can add animals and attributes easily without having to modify all the code.
A global variable is a variable that applies to the whole program. In your example, you say that habitat doesn't work, returning the error Global variable not initialized. It means that you might have declared habitat in some other function, maybe choicea, but you since you defined it in choicea, only choicea can access it. In other words, its not global. If you wanted it to be global, you should declare it outside of any functions, and, just to be safe, out of the loops too. Sometimes weird things happen with variables. Its a mistake everyone makes at some point in their programming life.
Also, instead of listing all that in your program, may I suggest using seperate files for them? Or a database to hold the values? This way, you don't have to modify the code every time that you want to change what the values start as... just a friendly suggestion.
Been there, made that mistake :-)
Define your global variable (eg. habitat) and 'global' at the beginning of each function that uses it.
A quick google came up with the following article:
http://effbot.org/pyfaq/how-do-you-set-a-global-variable-in-a-function.htm
Also look up 'global' in the python docs for the full explanation/description.
(btw, I think the tabulation was a bit broken when you copied your code into Stackoverflow)

Categories