This question already has answers here:
Check if a given key already exists in a dictionary
(16 answers)
Closed 9 years ago.
I have created a dictionary in python as my first 'major' project. I'm using it to keep track of key words as I go along. The entered are just examples so feel free to improve my definitions (:
I'm new to python so feel free to criticise my technique so I can learn before it gets any worse!
What I'm wondering is, would there be a way to deal with searches that are not included in the dictionary.
As in 'Sorry, the word you were looking for could not be found, would you like to try another search?'
Anyway, here's my code:
Running = True
Guide = {
'PRINT': 'The function of the keyword print is to: Display the text / value of an object',
'MODULO': 'The function of Modulo is to divide by the given number and present the remainder.'
'\n The Modulo function uses the % symbol',
'DICTIONARY': 'The function of a Dictionary is to store a Key and its value'
'\n separated by a colon, within the {} brackets.'
'\n each item must be separated with a comma',
'FOR LOOP': 'The For Loop uses the format: \n '
'For (variable) in (list_name): (Do this)',
'LINE BREAKS': ' \ n ',
'LOWERCASE': 'To put a string in lower case, use the keyword lower()',
'UPPERCASE': 'To put a string in upper case use the keyword upper()',
'ADD TO A LIST': 'To add items to a list, use the keyword: .append'
'\n in the format: list_name.append(item)',
'LENGTH': 'To get the length of a STRING, or list use the keyword len() in the format: len(string name)', }
while Running:
Lookup = raw_input('What would you like to look up? Enter here: ')
Lookup = Lookup.upper()
print Guide[str(Lookup)]
again = raw_input('Would you like to make another search? ')
again = again.upper()
if again != ('YES' or 'Y'):
Running = False
else:
Running = True
You can use a try/except block:
try:
# Notice that I got rid of str(Lookup)
# raw_input always returns a string
print Guide[Lookup]
# KeyErrors are generated when you try to access a key in a dict that doesn't exist
except KeyError:
print 'Key not found.'
Also, in order for your code to work, you need to make this line of code:
if again != ('YES' or 'Y'):
like this:
if again not in ('YES', 'Y'):
This is because, as it currently stands, your code is being evaluated by Python like so:
if (again != 'YES') or 'Y':
Furthermore, since non-empty strings evaluate to True in Python, having the code like this will make the if-statement always return True because 'Y' is a non-empty string.
Finally, you can completely get rid of this part:
else:
Running = True
since it does nothing but assign a variable to what it already equals.
Two options.
Use the in operator:
d = {}
d['foo'] = 'bar'
'foo' in d
Out[66]: True
'baz' in d
Out[67]: False
Or use the get method of your dictionary and supply the optional default-to argument.
d.get('foo','OMG AN ERROR')
Out[68]: 'bar'
d.get('baz','OMG AN ERROR')
Out[69]: 'OMG AN ERROR'
You can get what you want if you replace
print Guide[str(Lookup)]
with
badword = 'Sorry, the word you were looking for could not be found, would you like to try another search?'
print Guide.get(lookup,badword)
One thing that jumped out is naming your dict with a capital letter. Generally capital letters are saved for classes. Another kind of funny thing is that this is the first time I've seen a dict actually used as a dictionary. :)
Related
I'm not sure I understand what they're asking me to do here, so this is my attempt at doing it.
a='Swim'
b='Run'
if a!=b:
my_boolean = a!=b
print (my_boolean)
the excercise is only asking you to save the value of 'a!=b' in a variable.
However this should help you to understand the code better; you should save 'a != b' only once and then use 'my_boolean' every time you need it, but your code only prints true, because if 'my_boolean' is false, try this:
a = 'Swim'
b = 'Run'
my_boolean = a != b
print(my_boolean)
if my_boolean:
print('printing result: ' + str(my_boolean))
Let's get through it one-by-one. You are trying to compare two strings. If they are exactly the same you should get True otherwise you get False. Doing so would result in a Boolean or bool value.
So, your solution is inverted. It is expected to be:
a='Swim'
b='Run'
my_boolean = (a==b) # This value is boolean already. You can remove the brackets too. I put them for clarity
print (str(my_boolean)) # It works without saying str(), but I did that to show you that the value is converted from the type `bool` into the type String `str`.
I know this is relatively a basic question. I am trying to verify if given two sentences are synonym based on the given dictionary.
For example if dictionary is [(movie, film), (john, jack)] then "john likes movie" and "jack likes film" are synonym thus the function below will return true.
I changed each of two strings into the list of words by using lower/strip/split, then I tried to compare both lists by using for and if condition. I can't figure out where I did wrong.
def synonym_checker(synonyms, sentences):
a=sentences[0][0]
b=sentences[0][1]
a.lower()
b.lower()
a.strip()
b.strip()
aw=a.split()
bw=b.split()
import string
at = a.maketrans('','',string.punctuation)
bt = b.maketrans('','',string.punctuation)
ase = [w.translate(at) for w in aw]
bs = [w.translate(bt) for w in bw]
dictionary = dict(synonyms)
this = True
for i in range(0, min(len(ase), len(bs))):
if ase[i] != bs[i]:
if (bs[i] != dictionary[ase[i]]) and bs[i] not in [first for first, second in dictionary.items() if second == ase[i]]:
this = False
if (len(ase) != len(bs)):
this = False
is_synonym = this
print(ase)
print(bs)
return is_synonym # boolean
a = [("film", "movie"), ("revadfsdfs", "ads")]
b = [("I really want to watch that movie, as it had good fdf.", "I really want to watch that film, as it had good fdsaa")]
print(synonym_checker(a, b))
So, your error happened on
dictionary[ase[i]]
Because what you did here is actually
{'film': 'movie', 'revadfsdfs': 'ads'}['movie']
When your "movie" is not a key, but a value.
{'film': 'movie', 'revadfsdfs': 'ads'}
.. ^......... ^.............. ^ ............ ^
key .....value ....... key ....... value
The true problem here in my opinion is, your approach is not correct. Because dictionary is a one-way information, so when you want to check both 'film' to 'movie' and 'movie' to 'film', don't use a dictionary.
It also looks like you are trying to do something unnecessarily complicated for what you are trying to achieve.
a.lower()
b.lower()
a.strip()
b.strip()
Does not do anything to the actual program
The way you named your variables are also very hard to read, so maybe pick a proper name instead.
I'm running in to a problem with my code. What needs to happen is:
Program asks what your movie channel name is,
Program asks what the code is that you received,
Program checks whether the code you received matches the movie channel you specified,
Program returns a print statement based on the result. If the code was found, print "Match", otherwise print "not found"
The code I have so far is:
def code_controle():
moviechannel = input("What is the name of your movie channel?")
code = input("What is the code you want to check?")
list = [
["RTL8", "20:30", "Rush", "John", "Smith", "123"],
["Veronica", "15:00", "V for Vendetta", "Jane", "Smith" , "ABC"]
]
Now what I need to do is match the moviechannel with a code.
Basically, if I put in "RTL8" and the code "123" it should look through all the lists starting with RTL8, then check the code I put in, with the code in the list. If this matches each other, print "match".
A simple solution is to iterate over the main list and check if the movie and code both exist in any sublist.
Python allows for checking values in a list using in. It is simply if 'value' in list
Writing a method as the one below could be useful if you want to call it often.
for sublist in list:
if movie in sublist and code in sublist:
return True
return False
Edit:
The above code will return true even if the movie and code values are interchanged. If the code is an unique identifier it should be fine, as no movie title would match it.
Since the list is generated by reading from an .csv file, and we are assured that the movie will always be the first item and the code the sixth, we can use the below code for exactly matching only those values.
for sublist in list:
if (movie == sublist[0]) and (code == sublist[5]):
return True
return False
I would wrap that in a try/except to catch any Index out of range just to be safe.
You could tackle that using python dictionaries, but to continue with your example:
found=0
for x in list: #note, change this, list is a type def
if x[0]==code and x[-1]==channel:
found+=1
print "Match"
if (found==0):
print "No match"
I'm assuming this is what you mean:
for line in list:
if moviechannel in line and code in line:
print('Match')
return
print('not found')
Btw you really should reconsider renaming your list, since that is also a built in function.
try this:
>>> my_list = set([moviechannel] + [code])
>>> for x in list:
... if len(set(x) & my_list) == 2:
... print "Match"
...
Match
This is an other way to do it:
new_list = c_list[0] + c_list[1]
if code in new_list and moviechannel in new_list:
print 'Match'
else:
print 'Not found'
You should not use list as list is a built-in function so I changed it to c_list.
Okay so here's my dilemma:
I'm working on a FAQ bot for a subreddit. I'm having trouble with boolean logic and could use a pair of more experienced eyes (this is my first adventure in Python). Right now the bot is basically spamming the test subreddit I created. Rather than share that specific information, here's an example that is showing the exact problem I'm running into:
#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = ('system requirements' and '?')
sysReq2 = ('can' and ('handle' or 'play' or 'run') and ('netbook' or 'notebook' or 'pc' or 'mac' or 'macbook' or 'laptop' or 'comp' or 'computer') and '?')
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
print testString1
if (sysReq1 or sysReq2) in testString1.lower():
print sysReqResponse
print testString2
if (sysReq1 or sysReq2) in testString2.lower():
print sysReqResponse
print testString3
if (sysReq1 or sysReq2) in testString2.lower():
print sysReqResponse
When you run it, it displays:
i hate this
is that real?
PROGRESS
What are the system requirements?
PROGRESS
it keeps returning a value for testString2. I think it has something to do with '?' but really have no clue how or why or what to do about it. Help!
EDIT: Here's what I want it to display:
When you run it, it displays:
i hate this
is that real?
What are the system requirements?
PROGRESS
So far, I found that if I change my sysReq1 = ('system requirements' and '?') to sysReq1 = 'system requirements' '?' and only check the if for sysReq1, it returns the fight values. Problem is I really need those or statements to reduce clutter/redundancy.
The reason sysReq2 is there is because some people ask a different question for the same answer :
Can it run on my netbook?
Can my PC handle it?
Can I play it on my mac?
and this is excluding the variations of 'Will I be able to', but you get the idea. All of these should return the same value (in this case, "PROGRESS")
I think any, all, and generators can help you out here.
The code
#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = ['system requirements', '?']
sysReq2 = [['can']
,['handle', 'play', 'run']
,['netbook', 'notebook', 'pc', 'mac', 'macbook', 'laptop', 'comp', 'computer']
,['?']
]
def test(testString):
lowerTestString = testString.lower()
return all(i in lowerTestString for i in sysReq1) or all(any(j in lowerTestString for j in i) for i in sysReq2)
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
print testString1
if test(testString1):
print sysReqResponse
print testString2
if test(testString2):
print sysReqResponse
print testString3
if test(testString3):
print sysReqResponse
The function isn't strictly necessary, but it does make the code more maintainable. If you need to change the check, it only changes in one place.
What's going on here?
First, we converted the two sets of strings into a list and a list of lists. The requirement then becomes, "The string must contain all elements of sysReq1 or at least one element from every sublist of sysReq2."
We accomplish checking this condition by combining generators with the any and all functions. After storing the lower to avoid calling this repeatedly, we create a generator (which amounts to an iterator) of booleans. Each boolean tells us whether a single element of sysReq1 is contained in the lowered. Then we pass this iterator to the first all, which checks if the list contains all Trues. If so, the all function returns True and the second check is short circuited. Otherwise, it returns False and Python moves on past the or.
The check for sysReq2 is more complicated. First, we create a generator of booleans for each sublist; this is inside the any call. This list contains a set of booleans as to whether each element of the sublist is in the lowered string. The any call returns True if any element in this list of booleans (based on the sublist) is True. (It short circuits, by the way, and since we're using a generator, the checks following a True aren't even run, unlike if we had used a list.) Then we create another generator; this one contains the results of each sublist test (all the any calls). Then all is called on this generator, which checks if the question contained an element from all sublists.
I would note that users can enter nonsense questions if they're typing them in directly. For example, 'Play can netbook kuguekf ugifugfj ugufsgjf nugjfgjfgj?' would pass this check.
Summary
Use generators to run your tests that return boolean values. Use any and all to combine iterables of boolean values.
Edit
Based on comments, here's an alternate solution that splits the input string by white space and uses sets instead of lists. I also added a test case from the sample questions you listed to ensure that the second part of the or is being hit.
#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = set(['system', 'requirements'])
sysReq2 = [set(['can'])
,set(['handle', 'play', 'run'])
,set(['netbook', 'notebook', 'pc', 'mac', 'macbook', 'laptop', 'comp', 'computer'])
]
def test(testString):
if not testString.endswith('?'):
return False
lowerTestString = set(testString.rstrip('?').lower().split())
return lowerTestString.issuperset(sysReq1) or all(not lowerTestString.isdisjoint(i) for i in sysReq2)
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
testString4 = "Can my PC handle it?"
#intended result for 4: 'PROGRESS'
print testString1
if test(testString1):
print sysReqResponse
print testString2
if test(testString2):
print sysReqResponse
print testString3
if test(testString3):
print sysReqResponse
print testString4
if test(testString4):
print sysReqResponse
I think this is fairly straightforward. Note that the set constructor takes an iterable, so I'm passing lists in just for that. The "not disjoint" part might be a bit confusing; it's just making sure the intersection isn't empty. I used that in hopes that the function is implemented so that it doesn't compute the entire intersection. The question mark was problematic since it wasn't separated by a space, so I just made sure the string ended in a question mark and rstriped it off.
Actually, this implementation might be cleaner and more maintainable than the one with lots of generators.
Two problems. First, you can't use and and or to "store" some kind of comparison operator for use later. When you write and and or the result is evaluated immediately. The rules for that are described in the documentation.
Second, you can't use and and or with in that way. in does not "distribute over" and and and or. Writing ('A' and 'B') in x doesn't mean "A in x and B in x". It evaluates ('A' and 'B') first (which in this case will give you 'B') and then checks whether that single result is in x.
You can't achieve what you want with simple operators. There's no way to use just the and and or operators to store a complex query like that that you can apply later. You're going to have to convert your criteria into functions and call them with the "test strings" as arguments:
def sysReq1(x):
return 'system requirements' in x and '?' in x
>>> testString2 = "is that real?"
... testString3 = "What are the system requirements?"
... print testString2
... if sysReq1(testString2.lower()):
... print "2 passed the test"
... print testString3
... if sysReq1(testString3.lower()):
... print "3 passed the test"
is that real?
What are the system requirements?
3 passed the test
I'd suggest you work through the Python tutorial to get a handle on the basics of Python.
In python, the output of an expression containing BOOLEAN OPERATORS need not be a BOOLEAN (http://docs.python.org/2/library/stdtypes.html)
e.g., sysReq1 = ('system requirements' and '?') will make sysReq1='?' and note here that sysReq1 is not a boolean value but a string equalling to QUESTION MARK. Similarly, sysReq2 will also be equal to ? . And also, look for TRUTH VALUE TESTING in the above link as that will explain what values will be considered as FALSE expressions.
I am trying to cursor search through some records in an access table from a field called DEV_TYPE. I want to compare each record against a list of know values I have built earlier in my script:
(devcatList)
I want to print out any values that do not occur in the list. Some of the values in the records are Null as well. I want to set my if statement to only print out values that do not occur in the list, but I also do not want to print out 'None' for the Null values. My script is as follows:
if field.name == "DEV_TYPE":
for iRow in arcpy.SearchCursor(fc):
if not iRow.DEV_TYPE is None or iRow.DEV_TYPE not in devcatList:
print str(iRow.OBJECTID) + " - " + str(iRow.DEV_TYPE)
I've played around with the 'if not x is None' to 'if x is not None'. Changed the 'or' to and 'and' (even though it was counter intuitive), but my printouts either return all values or no values or only 'None'....basically everything I don't want. I'm sure I'm doing something silly. Can someone point out what my silliness is?
Thanks,
Mike
I think you want if iRow.DEV_TYPE is not None and iRow.DEV_TYPE not in devcatList:
Maybe something like this:
if field.name == "DEV_TYPE":
for iRow in arcpy.SearchCursor(fc):
dev_type = iRow.DEV_TYPE
if dev_type is not None and dev_type not in devcatList:
print "{} - {}".format(iRow.OBJECTID, iRow.DEV_TYPE)
The if dev_type is not none can be more conveniently (but less precisely) stated if dev_type since None is equivalent to False in a conditional context. I also took the liberty of rewriting the print statement in a more idiomatic fashion.