I am having problems printing values from a dictionary I made. The dictionary contains a word as a key and a description of that word as a value. The problem I run into is in the function that is supposed to print the description of a word (lookup) that the user puts in is not working as I want it to.
I have implemented a for loop to search for the word the user wants to look up in the dictionary and then print the description (value) of that word. and it kinda works. The problem is that if for example, the dictionary would have a word: banana and apple and description: yellow and fruit. It will work if I want to look up "apple". Then it will print "description of apple: fruit".
The problem appears if I then want to look up the description of "banana". Because it is a loop (and the latest value of word was apple I guess) it will first go through and print "the word is not in the dictionary!" and then print "description of banana: yellow". So I'm thinking to get past this problem I should implement another way of finding the key than a loop. I just don't know how.
def dictionary():
dictionary = {}
while True:
print("\n--- Menu for dictionary ---\n Choose 1 to insert a new word\n Choose 2 to find the description of a word\n Choose 3 to exit\n")
answer = input("Type your answer here: ")
if answer == "1":
insert(dictionary)
elif answer == "2":
lookup(dictionary)
elif answer == "3":
break
else:
print("\nTry again!\n")
def insert(dictionary):
word = input("Type the word you want to add: ")
description = input("Type a description of the word: ")
if word in dictionary:
print("\nThe word already exists in the dictionary!\n")
return
else:
dictionary[word] = description
def lookup(dictionary):
wordsearch = input("What word would you like to lookup: ")
for word, description in ordlista.items():
if word == wordsearch:
print("\nDescription of", word,":", description)
break
else:
print("The word is not in the dictionary!")
You just need to remove the else condition and make sure that you print the second statement only when the loop is over (and never hit the break part).
With the current version of your code that conditional is execute for every iteration of the loop so if it fails it just prints the "Not found".
Here's an example:
def dictionary():
dictionary = {}
while True:
print("\n--- Menu for dictionary ---\n Choose 1 to insert a new word\n Choose 2 to find the description of a word\n Choose 3 to exit\n")
answer = input("Type your answer here: ")
if answer == "1":
insert(dictionary)
elif answer == "2":
lookup(dictionary)
elif answer == "3":
break
else:
print("\nTry again!\n")
def insert(dictionary):
word = input("Type the word you want to add: ")
description = input("Type a description of the word: ")
if word in dictionary:
print("\nThe word already exists in the dictionary!\n")
return
else:
dictionary[word] = description
def lookup(dictionary):
wordsearch = input("What word would you like to lookup: ")
for word, description in dictionary.items():
if word == wordsearch:
print("\nDescription of", word,":", description)
break
print("The word is not in the dictionary!")
dictionary()
I also want to add that looping through all the values in the dictionary may not be very efficient if your dictionary is very big.
For this reason I'd like also to suggest another solution using using get():
def dictionary():
dictionary = {}
while True:
print("\n--- Menu for dictionary ---\n Choose 1 to insert a new word\n Choose 2 to find the description of a word\n Choose 3 to exit\n")
answer = input("Type your answer here: ")
if answer == "1":
insert(dictionary)
elif answer == "2":
lookup(dictionary)
elif answer == "3":
break
else:
print("\nTry again!\n")
def insert(dictionary):
word = input("Type the word you want to add: ")
description = input("Type a description of the word: ")
if word in dictionary:
print("\nThe word already exists in the dictionary!\n")
return
else:
dictionary[word] = description
def lookup(dictionary):
wordsearch = input("What word would you like to lookup: ")
if dictionary.get(wordsearch):
print("\nDescription of", wordsearch,":", dictionary.get(wordsearch))
else:
print("The word is not in the dictionary!")
dictionary()
Here's some basic information the Get method I used:
Get Parameters
get() Parameters get() method takes maximum of two parameters:
key - key to be searched in the dictionary value (optional) - Value to
be returned if the key is not found. The default value is None. Return
Value from get() get() method returns:
the value for the specified key if key is in dictionary. None if the
key is not found and value is not specified. value if the key is not
found and value is specified.
Get returns
Return Value from get() get() method returns:
the value for the specified key if key is in dictionary. None if the
key is not found and value is not specified. value if the key is not
found and value is specified.
More information about the Python dictionary's get() method available here.
Norie has it right - here's a little more detail. Your function:
def lookup(dictionary):
wordsearch = input("What word would you like to lookup: ")
for word, description in ordlista.items():
if word == wordsearch:
print("\nDescription of", word,":", description)
break
else:
print("The word is not in the dictionary!")
can be rewritten to use get instead of iterating through the keys:
def lookup(dictionary):
wordsearch = input("What word would you like to lookup: ")
look_result = ordlista.get(wordsearch)
print(f"\nDecription of {word}: {look_result}" if look_result else "\nThe word is not in the dictionary!")
Related
I've been set a task by my lecturer to complete a couple challenges to help improve my understanding of dictionaries and the concepts behind them. I've been able to complete the first task quite easily but I'm quite stuck with the second task. The first task was to create a 'Who's your Daddy? program'.
The challenge states: Write a Who's Your Daddy program that lets the user enter the name of a male and produces the name of his father. (You can use celebrities, fictional characters, or even historical figures for fun.) Allow the user to add, replace, and delete son-father pairs.
I was able to create this challenge with only one issue where I could only replace a father of a son and not both.
The second challenge states: Improve this program by adding a choice that lets the user enter a name and get back a grandfather. Your program should still only use one dictionary of son-father pairs. Make sure to include several generations in you dictionary so that a match can be found.
I thought that I could maybe use a dictionary nested in a dictionary and researched that, but it only stated one dictionary. I then thought could I use a tuple within a dictionary and then access this tuple when the user requests a son and their grandfather, but have not had much luck with this either, so I decided to come on here.
So now I wonder, how can I add grandfathers to each of the pairs, can you add a second value to a key in a dictionary?
names = { "henry" : "michael",
"louis" : "jason",
"owen" : "justin",
"jake" : "glynn",
"adam" : "mark",
}
choice = None
while choice != "0":
print(
"""
Welcome to the Who's Your Daddy? program.
You can find out a father of the names listed,
you can then add, replace and delete a son/father pair.
0 - Exit
1 - List sons and their fathers
2 - Add a pair
3 - Replace a pair
4 - Delete a pair
"""
)
choice = input("Choice: ")
#exit
if choice == "0":
print("Goodbye")
#List sons
if choice == "1":
print(*names.keys(), sep='\n')
son_choice = input("Who's father would you like to know the name of?: ")
if son_choice in names:
print(names[son_choice])
else:
print("That name is not in the list!")
#Add a pair
elif choice == "2":
son_add = input("Enter the name of someone: ").lower()
if son_add not in names:
father_add = input("Now enter the name of their father: ").lower()
names[son_add] = father_add
print("That pair has been added")
else:
print("That name already exists!")
#Replace a pair
elif choice == "3":
son_replace = input("What name do you want to replace?: ")
if son_replace in names:
father_replace = input("Enter the name of their father: ")
names[son_replace] = father_replace
print("The pair has been replaced")
else:
print("That name doesn't exist, please add it first!")
#Delete a pair
elif choice == "4":
son_delete = input("What name do you want me to delete?: ")
if son_delete in names:
del names[son_delete]
print("Pair deleted!")
else:
print("That pair does not exist!")
else:
print("Sorry, that's an invalid choice!")
input("\n\nPress the enter key to exit!")
With the help of Ronald and a little common sense I've now solve this issue.
For a grandfather to be found, I needed to create a new son father pair where the son's father would be a son already in the list. For example, if I create a new pair, with the son being called tom and the father being called henry. I can then use the find the grandfather function to show that tom's grandfather would be michael.
#Find a grandfather
elif choice == "5":
grandson = input("Please enter the son and I will find the grandfather: ").lower()
if grandson in names:
father = names[grandson]
if father in names:
grandfather = names[father]
print("The grandfather of " + grandson + " is " + grandfather)
else:
print(father + " is not in the dictionary")
else:
print(grandson + " is not in the dictionary")
This is the code I created, however, how would I make this work for several generations, or is that already accomplished by this piece of code.
This question already has answers here:
Making objects iterable?
(3 answers)
Closed 3 years ago.
I'm new to python and am trying to implement some of the new things I've learnt over my course and am trying to define a dictionary class that has a function that allows it to be iterated through and displayed however when compiled and ran, I get a TypeError: object is not iterable.
I'm working on pycharm and can't seem to figure out what the problem is. I've been able to get rid of the error through rewriting some of the code however that just results in no output.
class Dict:
def __init__(self):
self.UserDict = {}
def __setitem__(self, key, item):
self.__dict__[key] = item
# def __getitem__(self, key):
# self.__dict__[key]
def KeyandVal(self, dic, key, val):
dic[key] = val
def SwapVal(self, dic, key1, key2):
temp = ""
temp = dic[key1]
dic[key1] = dic[key2]
dic[key2] = temp
def display(self, dic):
for dic.UserDict.key, dic.UserDict.value in dic.UserDict:
print(dic.UserDict[dic.UserDict.key])
choice = 1
UserDict = Dict()
while True:
print("------------------------------")
print("")
print("1. Create a key and value pair")
print("2. Change the value of a key")
print("3. Swap key values")
print("4. Display Dictionary")
print("5. Export data to new file")
print("6. Logout")
print("")
choice = input("Please enter a number for the desired task or '0' to Exit: ")
if choice == "0":
print("Thank you!")
time.sleep(1)
break
elif choice == "1":
key = input("What would you like to name this key?: ")
val = input("What would you like its value to be?: ")
UserDict.KeyandVal(UserDict, key, val)
elif choice == "2":
key = input("Which key value would you like to change?: ")
val = input("Enter new value: ")
UserDict.KeyandVal(UserDict, key, val)
elif choice == "3":
key1 = input("Enter first key: ")
key2 = input("Enter second key: ")
UserDict.SwapVal(UserDict, key1, key2)
print("Values Swaped!")
elif choice == "4":
UserDict.display(UserDict)
Preferably, once the display function is ran, the key and value pairs should be outputted. Again, nothing is outputted instead.
On the line for dic.UserDict.key, dic.UserDict.value in dic.UserDict:, specifically on in dic.UserDict you are implicitly calling the __iter__ method of your Dict class, which isn't implemented. That's why you are seeing this TypeError: object is not iterable.
For more info take a look at this method's docs.
Hello everyone so I have an issue trying to find the user input in a dictionary.
My function is getting data from a website and writing it to a text file. Then transferred into a dictionary, from there I will ask the user to input a country name and it will return the key and the value of that key or the capita income. The issue i am having is that i have to search the dictionary to find the input and if it matches the key then it will print that and the capita income. Im not 100 percent sure what to use if i should use a for function or if my code is correct at the end.
def main():
import requests
webFile = "https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2004.txt"
data = requests.get(webFile) #connects to the file and gest a response object
with open("capital.txt",'wb') as f:
f.write(data.content) #write the data out to a file – wb used since thecontent from the response object is returned as abinary object.
f.close()
countryName = {}
with open('capital.txt','r') as infile:
for line in infile:
num,*key,value = line.split()
key = ' '.join(key)
countryName[key] = value.upper()
userInput = input("Enter a country name: ")
userInput.upper()
while(userInput != 'stop'):
#for loop to see if key is in dictionary
if userInput in countryName:
#if(userInput == countryName[key]):
print("The per capita income in",key, "is",countryName[key])
userInput = input("Enter a country name: ")
main()
while(userInput != 'stop'):
#for loop to see if key is in dictionary
if userInput in countryName:
#if(userInput == countryName[key]):
print("The per capita income in",key, "is",countryName[key])
userInput = input("Enter a country name: ")
main()
Here is where the issue is, tying to find the if the userInput is the same as the country name key . What would i have to do search the dictionary to match the key to the input, or if there is any uneccesary things in my code.
Update 2
Ah, there was a small issue when comparing the keys. Actually, you were doing upper() on the value (a number) which doesn't make sense.
Have a look at this update:
import requests
webFile = "https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2004.txt"
data = requests.get(webFile)
with open("capital.txt",'wb') as f:
f.write(data.content)
countryName = {}
with open('capital.txt','r') as infile:
for line in infile:
num, *key, value = line.split()
key = ' '.join(key)
countryName[key.upper()] = value #key.upper() instead of value.upper()
userInput = input("Enter a country name: ").upper()
counter = 0
while not userInput == "STOP": #'STOP' because it's uppercase
if userInput in countryName:
print("The per capita income in", userInput, "is", countryName[userInput])
userInput = input("Enter a country name: ").upper()
counter += 1
if counter >= len(countryName): #It couldn't find the country
userInput = input("Not found. Enter a new country: ").upper()
counter = 0 #Let's try again
And a small improvement: the counter will prevent the infinite loop when the user input doesn't satisfy the if userInput in countryName and it's not "stop". Besides that, the "stop" condition must be "STOP", once it'll be in upper case.
Hope it helps
Update
As pointed out by #Barmar, another possibility is:
countryName = {
"countryA": "valueA",
"countryB": "valueB"
}
userInput = "countryA" #Of course, it can be a user input
if userInput in countryName:
print ("The country is", userInput, "and the value is", countryName[userInput])
Just a good advice: I think the file part has nothing to do with your question itself, so, next time try to reduce your problem to, you know, something more direct :)
Anyway, you can loop over the keys of countryName and then compare with the user input. In other words:
countryName = {
"countryA": "valueA",
"countryB": "valueB"
}
userInput = "countryA" #Of course, it can be a user input
for key in countryName.keys():
if userInput == key: #Got it
print ("The country is", key, "and the value is", countryName[key])
Hope it helps
While this assignment is past due (I joined the class late unfortunately) I still need to figure it out. I have the following list of words:
abhor:hate
bigot:narrow-minded, prejudiced person
counterfeit:fake; false
enfranchise:give voting rights
hamper:hinder; obstruct
kindle:to start a fire
noxious:harmful; poisonous; lethal
placid:calm; peaceful
remuneration:payment for work done
talisman:lucky charm
abrasive:rough; coarse; harsh
bilk:cheat; defraud
I need to read this file into a dictionary, pick a random key, scramble it, then ask the user to solve it. Unlike other solutions on here, it does not iterate three times, but runs until the user enters 'n'. The code will ask the user after each round if the user wants to continue the game. The user can also type 'hint' to get the definition of the word.
There is a similar question here: (http://www.dreamincode.net/forums/topic/302146-python-school-project-write-a-word-scramble-game-status-complete/) or rather the result of a question, but I am not knowledgeable enough to bridge the gaps and make it work for my purposes. None of the variation on this that I have seen on stack overflow come close enough for me to bridge the gap either, likely because I just don't know enough yet. Before we even start, this code does not yet work at all really, I am pretty lost at this point, so please be gentle. My code so far is below:
import random
from random import shuffle
#Reads the words.txt file into a dictionary with keys and definitions
myfile = open("words.txt", "r")
wordDict = dict([(line[:line.index(":")], line[line.index(":") +1 : -1])
for line in myfile.readlines()])
#print (b)
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
print('If you need a hint, type "Hint"\n')
#Picks a random key from the dictionary b
def shuffle_word():
wordKey = random.choice(list(wordDict.keys()))
return wordKey
#Gives a hint to the user
def giveHint(wordKey):
hint = wordDict[wordKey]
return hint
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def getAnswer():
answer = input('\nEnter your first guess: ')
while True:
if answer.isalpha():
return answer
else:
answer = input('\nPlease enter a letter: ')
def keepPlaying():
iContinue = input("\nWould you like to continue? ")
return iContinue
def scramble():
theList = list(shuffle_word())
random.shuffle(theList)
return(''.join(theList))
#Main Program
if keepPlaying() == 'y':
intro()
shuffle_word()
randomW = shuffle_word()
#scramKey = list(randomW)
thisWord = scramble()
print ("\nThe scrambled word is " +thisWord)
solution = getAnswer()
if solution == thisWord:
print("\nCongratulations")
if solution == 'Hint' or solution == 'hint':
myHint = giveHint(wordKey)
print(myHint)
else:
print("\nThanks for playing")
I have edited this post to ask for new information, though I am not sure if that ishow its properly done. Thanks to the help of those below, I have made progress, but am stuck not on a specific piece.
I have two questions. 1: How can I get the giveHint() function to return the definition of the random key selected by the shuffle_wprd() function. I know what I have above will not work because it is simply returning a string, but it seems like just using a dict.get() function would not get the correct definition for the random word chosen.
2: How can I get the program not to ask the user to continue on the first pass, but to then ask from then on. I thought about using a while loop and redefining the variable during the iteration, but I don't know enough to get it to work properly.
regardless, thank you to those people who have already helped me.
This should help you out a bit, the length seems to be of no benefit as a hint as you can see the length of the scrambled word so I used the definition as the hint,I think you also want to ask the user to guess the word not individual letters:
from random import shuffle, choice
#Reads the words.txt file into a dictionary with keys and definitions
with open("words.txt") as f:
word_dict = {}
for line in f:
# split into two parts, word and description
word, hint = line.split(":")
word_dict[word] = hint
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
#Picks a random key from the dictionary b
def pick_word():
word = choice(list(word_dict.keys()))
return word
#Gives a hint to the user
def give_hint(word):
# return the definition of the word
descrip = word_dict[word]
return descrip
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def get_answer():
while True:
answer = input('Please enter a guess: ')
if answer.isalpha():
return answer
else:
print("Only letters in the word")
def main():
intro()
word = pick_word()
# give user lives/tries
tries = 3
shffled_word = list(word)
# shuffle the word
shuffle(shffled_word)
# rejoin shuffled word
shffled_word = "".join(shffled_word)
# keep going for three tries as most
while tries > 0:
inp = input("Your scrambled word is {}\nEnter h if you want to see your hint or any key to continue".format(shffled_word))
if inp == "h":
print("The word definition is {}".format(give_hint(word)))
ans = get_answer()
if ans == word:
print("Congratulations you win!")
break
tries -= 1
# ask user if they want to play again, restarting main if they do
play_again = input("Press 'y' to play again or any key to exit")
if play_again == "y":
main()
# else the user did not press y so say goodbye
print("Goodbye")
main()
There are a few more bits to be added but I will leave that up to you.
Thank you to all those who helped. For any who come along later, the final product is here. Similar to what Padraic Cunningham put, but without the three answer limit, and without his more elegant solution of wrapping the main program into a called function.
import random
from random import shuffle, choice
#Reads the words.txt file into a dictionary with keys and definitions
with open("words.txt") as f:
wordDict = {}
for line in f:
# split into two parts, word and description
word, hint = line.split(":")
wordDict[word] = hint
#print (b)
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
print('If you need a hint, type "Hint"\n')
#Picks a random key from the dictionary b
def shuffle_word():
wordKey = choice(list(wordDict.keys()))
return wordKey
#Gives a hint to the user
def giveHint(wordKey):
descrip = wordDict[word]
return descrip
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def getAnswer():
answer = input('\nEnter a guess: ')
while True:
if answer.isalpha():
return answer
else:
answer = input('\nPlease enter a letter: ')
def getAnswer2():
answer2 = input('\nEnter another guess: ')
while True:
if answer2.isalpha():
return answer2
else:
answer2 = input('\nPlease enter a letter: ')
def keepPlaying():
iContinue = input("\nWould you like to continue? ")
return iContinue
#def scramble():
# theList = list(shuffle_word())
# random.shuffle(theList)
# return(''.join(theList))
#Main Program
while keepPlaying() == 'y':
intro()
#shuffle_word()
randomW = shuffle_word()
cheatCode = giveHint(randomW)
#scramKey = list(randomW)
thisWord = list(randomW)
print(thisWord)
random.shuffle(thisWord)
print(thisWord)
thisRWord = ''.join(thisWord)
print ("\nThe scrambled word is " +thisRWord)
solution = getAnswer()
loopMe = False
while loopMe == False:
if solution == randomW:
print("\nCongratulations")
loopMe = True
if solution == 'Hint' or solution == 'hint':
print(cheatCode)
if solution != randomW:
loopMe = False
solution = getAnswer2()
OK so what I need to do is make my code only allow the user to enter one letter and then one symbol at a time. The example below shows what I want in a better view.
At the moment my code allows the user to enter more than one character at a time which I don't want.
What letter would you like to add? hello
What symbol would you like to pair with hello
The pairing has been added
['A#', 'M*', 'N', 'HELLOhello']
What I want is a message to be displayed like this and the pairing not to be added to the list.
What letter would you like to add? hello
What symbol would you like to pair with hello
You have entered more than one character, the pairing was not added
['A#', 'M*', 'N',].
So far my code for this section is as follows...
It would also be great for when the user enters a number in the letter section, an error message to be printed.
def add_pairing(clues):
addClue = False
letter=input("What letter would you like to add? ").upper()
symbol=input("\nWhat symbol would you like to pair with ")
userInput= letter + symbol
if userInput in clues:
print("The letter either doesn't exist or has already been entered ")
elif len(userInput) ==1:
print("You can only enter one character")
else:
newClue = letter + symbol
addClue = True
if addClue == True:
clues.append(newClue)
print("The pairing has been added")
print (clues)
return clues
The easiest way to ensure user input is with a loop:
while True:
something = raw_input(prompt)
if condition: break
Something set up like this will continue to ask prompt until condition is met. You can make condition anything you want to test for, so for you, it would be len(something) != 1
Your method can be simplified to the following if you let the user enter a letter and symbol pair:
def add_pairing(clues):
pairing = input("Please enter your letter and symbol pairs, separated by a space: ")
clues = pairing.upper().split()
print('Your pairings are: {}'.format(clues))
return clues
Not exactly sure what you want to return but this will check all the entries:
def add_pairing(clues):
addClue = False
while True:
inp = input("Enter a letter followed by a symbol, separated by a space? ").upper().split()
if len(inp) != 2: # make sure we only have two entries
print ("Incorrect amount of characters")
continue
if not inp[0].isalpha() or len(inp[0]) > 1: # must be a letter and have a length of 1
print ("Invalid letter input")
continue
if inp[1].isalpha() or inp[1].isdigit(): # must be anything except a digit of a letter
print ("Invalid character input")
continue
userInput = inp[0] + inp[1] # all good add letter to symbol
if userInput in clues:
print("The letter either doesn't exist or has already been entered ")
else:
newClue = userInput
addClue = True
if addClue:
clues.append(newClue)
print("The pairing has been added")
print (clues)
return clues
I am fan of raising and catching exceptions in similar cases. Might be shocking for people with 'C-ish' background (sloooow), but it is perfectly pythonic and quite readable and flexibile in my opinion.
Also, you should add check for characters outside of set you are expecting:
import string
def read_paring():
letters = string.ascii_uppercase
symbols = '*##$%^&*' # whatever you want to allow
letter = input("What letter would you like to add? ").upper()
if (len(letter) != 1) or (letter not in letters):
raise ValueError("Only a single letter is allowed")
msg = "What symbol would you like to pair with '{}'? ".format(letter)
symbol = input(msg).upper()
if (len(symbol) != 1) or (symbol not in symbols):
raise ValueError("Only one of '{}' is allowed".format(symbols))
return (letter, symbol)
def add_pairing(clues):
while True:
try:
letter, symbol = read_paring()
new_clue = letter + symbol
if new_clue in clues:
raise ValueError("This pairing already exists")
break # everything is ok
except ValueError as err:
print(err.message)
print("Try again:")
continue
# do whatever you want with letter and symbol
clues.append(new_clue)
print(new_clue)
return clues