This question already has answers here:
Dictionary Help! Extracting values and making a table
(2 answers)
Closed 8 years ago.
Here's the question that I'm supposed to code for:
Write the contract, docstring and implementation for a function showCast that takes a movie title and prints out the characters with corresponding actors/actresses from the given movie in an alphabetical order of characters. The columns must be aligned (20 characters (including the character's name) before the name of the actor/actress.) If the movie is not found, it prints out an error message.
It gives an example of what's supposed to happen here
>>> showCast("Harry Potter and the Sorcerer's Stone")
Character Actor/Actress
----------------------------------------
Albus Dumbledore Richard Harris
Harry Potter Daniel Radcliffe
Hermione Granger Emma Watson
Ron Weasley Rupert Grint
>>> showCast('Hairy Potter')
No such movie found
Here are other functions that I've written for the same project that will probably be of assistance in answering the question. A summary of what I've had to do so far is that I'm creating a dictionary, called myIMDb, with a key of the title of the movie, and the value another dictionary. In that dictionary that key is a character of a movie, and the value is the actor. And I've done stuff with it. myIMDb is a global variable for the record.
Other functions, what they do is the docString
def addMovie (title, charList, actList):
"""The function addMovie takes a title of the movie, a list of characters,
and a list of actors. (The order of characters and actors match one
another.) The function addMovie adds a pair to myIMDb. The key is the title
of the movie while the value is a dictionary that matches characters to
actors"""
dict2 = {}
for i in range (0, len(charList)):
dict2 [charList[i]] = actList[i]
myIMDb[title] = dict2
return myIMDb
I've added three movies,
addMovie("Shutter Island", ["Teddy Daniels", "Chuck Aule"],["Leonardo DiCaprio, ","Mark Ruffalo"])
addMovie("Zombieland", ["Columbus", "Wichita"],["Jesse Eisenberg, ","Emma Stone"])
addMovie("O Brother, Where Art Thou", ["Everett McGill", "Pete Hogwallop"],["George Clooney, ","John Turturro"])
def listMovies():
"""returns a list of titles of all the movies in the global variable myIMDb"""
return (list(myIMDb.keys()))
def findActor(title, name):
""" takes a movie title and a character's name and returns the
actor/actress that played the given character in the given movie. If the
given movie or the given character is notfound, it prints out an error
message"""
if title in myIMDb:
if name in myIMDb[title]:
return myIMDb[title][name]
else:
return "Error: Character not in Movie"
else:
return "Error: No movie found"
Now where I'm having trouble
I'm supposed to write the showCast function, but I'm having a lot of trouble. I've been tinkering with it for a while but when I call myIMDb.values() everything returns. And I can't seem to loop through it to sort them to create the table.
Here's what I've come up with so far, but it doesn't do what I was hoping. I'm just hoping that one of you can steer me in the right direction. (The commented out region is what I was doing before, just so you can see my train of thought. [the print(alist) and print(alist[0]) was just to confirm that it's one big entry in a list, not separated at all])
def showCast(title):
if title in myIMDb:
actList=[]
chList=[]
aList = list(myIMDb.values())
print (aList)
print (aList[0])
""""for i in range (len(aList)):
if i%2==0:
chList.append(aList[i])
else:
actList.append(aList[i])
print(chList)
print(actList)""""
else:
return "Movie not Found"
It's an old question, but I'll take a stab. I think your confusion comes from the nested nature of the myIMDb object. To get back information about a specific movies, you should use the title as a key to myIMDb, e.g. myIMDb[title]. What you get back is another dictionary, that you can then use to get the character/actor key value pairs.
Here's a working version of the showCast function:
def showCast(title):
if title in myIMDb:
print("{0:20} {1:20}".format("Character", r"Actor/Actress"))
print("-"*40)
for character, actor in myIMDb[title].items():
print("{0:20} {1:20}".format(character, actor))
else:
return "Movie not Found"
The first print statement generates the heading, and uses the Python's format string method to get the aligned spacing that you want. The next print statement is the divider, and then the meat of the function is simply iterating over the pairs with a for loop.
I hope that helps.
Related
I transfer form JAVA and pretty new in python.I knew python is a convenience language. Then I consider if or not a way I could use in print(''.format()) function to print a list, which I insert couple of word in between value.
I have already tried print(''.format(for i in list)) as simple example showed below:
movies.append(1)
movies.append('The Shawshank Redemption')
movies.append('5 star')
movies.append('whatever')
movies.append('www.google.com')
print('''
The NO.{} Movie is :{}
Rating:{}
Quote:{}
Link:{}
'''.formate(for i in movie)
of course, it shows error invalid syntax at last statement.
for i in movies is a for statement, so it expects to have a block of code.
What you want is to get every item for item in movies, and then pass each item to the function, so you should do this instead
print('''
The NO.{} Movie is :{}
Rating:{}
Quote:{}
Link:{}
'''.format(*(i for i in movie)) # '*' unpacks the generator, so instead of passing a whole object to the function, you pass every object in the generator as an argument
Note that you can actually pass the unpacked list to format like so
print('''
The NO.{} Movie is :{}
Rating:{}
Quote:{}
Link:{}
'''.format(*movies) # '*' unpacks the generator, so instead of passing a whole object to the function, you pass every object in the generator as an argument
*movies unpack argument lists
movies = []
movies.append(1)
movies.append('The Shawshank Redemption')
movies.append('5 star')
movies.append('whatever')
movies.append('www.google.com')
print('The NO.{}\nMovie is :{}\nRating:{}\nQuote:{}\nLink:{} '.format(*movies))
Output is
The NO.1
Movie is :The Shawshank Redemption
Rating:5 star
Quote:whatever
Link:www.google.com
I have a list with movie names:
Movie List
And another list of questions about movies:
List of questions
My objective is to loop through the list of questions and each time the function finds a name in the question that is in the list of movies, changes the name to "MOVIE".
At the moment i can do it for each question:
def remove_movie_name_1(text):
for i in tqdm(range(len(movies))):
return re.sub(movies[42], 'MOVIE', text)
remove_movie_name_1(tq[21])
This way i can change it for example from "What was the role played by Tim Allen in Toy Story 3?" to "What was the role played by Tim Allen in MOVIE?"
When i tried to apply it to the whole list I used this code:
def remove_movie_name(text):
for i in tqdm(range(len(movies))):
return re.sub(movies[i], 'MOVIE', text)
for i in tqdm(range(len(tq))):
tq[i] = remove_movie_name(tq[i])
But this code doesn't change anything and I can't see what's the problem.
Thank you.
def remove_movie_name(text):
for i in tqdm(range(len(movies))):
return re.sub(movies[i], 'MOVIE', text)
return exits the function immediately. Your loop only runs one time.
I am trying to append a random choice into a dictionary, but my code doesn't seem to be working.
The file I am using (mood.txt):
happy, Jennifer Clause
happy, Jake Foster
sad, Jonathan Bower
mad, Penny
excited, Logan
awkward, Mason Tyme
my code:
def theFile():
moodFile = open("mood.txt")
theMood = moodFile.readlines()
moodFile.close()
return(theMood)
def makeTheDict(myFile):
moodDict = {}
for lines in myFile:
(mood, name) = lines.split(",")
moodDict[mood] = name.strip()
return(moodDict)
def randomMood(name, mood, moodDict):
if mood in moodDict:
randomMood = random.choice(mood)
moodDict[mood] = randomMood
moodDict.append(name, randomMood)
print(name, "has been put in the", randomMood, "group")
def main():
moodFile = theFile()
moodDict = makeTheDict(moodFile)
name = input("Choose a name: ")
newMood = input("Choose a mood: ")
randomMood(name, newMood, moodDict)
For example, I want to add a "Jamie Green" into a random group, and if it randomly chose "sad" then -
happy, Jennifer Clause
happy, Jake Foster
sad, Jonathan Bower
mad, Penny
excited, Logan
awkward, Mason Tyme
#sad, Jamie Green
How would I append this into the dictionary randomly?
Thank you!
It seems that you want to map strings to lists of strings, but instead of that you are mapping strings to strings.
Look at this line:
moodDict[mood] = name.strip()
Here you are mapping the string mood to the string name.strip(). If at this point, there was already a name mapped to the current mood, the old value would be replaced and lost. In your file sample, both Jennifer and Jake are happy. At the first iteration of the for loop you have:
moodDict["happy"] = "Jennifer Clause"
Then, at the second step, you have.
moodDict["happy"] = "Jake Foster"
Here "Jake Foster" replaces "Jennifer Clause". Since the moods can be repeated, what you probably want is something like this:
if mood in moodDict:
moonDict[mood].append(name.strip())
else:
moonDict[mood] = [name.strip()]
This way, for each mood key you have a list of name values.
Regarding the randomMood function, there are may things doesn't look good:
The if statement should be indented since is part of the function. This should throw an IndentationError, but I will assume it happened when you copied the code into StackOverflow.
Mood is a string, so what you are actually doing in random.choice(mood) is to choose a random character from that string, which doesn't make any sense. You probably want to choose from the list of moods, which would be something like this randomMood = random.choice(moodDict.keys()).
Because of what I explained in the previous point, the following line just replace the value under the mood key with a random character from the mood, which doesn't make sense.
Dictionaries don't have any method named append, this should throw an error too. You probably want to replace it with this: moonDict[randomMood].append(name)
Finally, I don't understand why you ask the user to input a mood when it is supposed to be chosen randomly.
It seems you are a bit confused about what a Python dictionary is and how it works. Remember that it map keys to values. In your code your keys are the moods and the values are the names, both represented as strings. The keys are unique. This means that if you assign a new value to an existing key, the old value mapped under that key gets lost. If you want to deal with multiple values under the same key you should map the key to a collection of values, like a list, instead of a single value.
This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 6 years ago.
I'm programming the board game Monopoly in Python. Monopoly has three types of land that the player can buy: properties (like Boardwalk), railroads, and utilities. Properties have a variable purchase price and rents for 6 conditions (0-4 houses, or a hotel). Railroads and utilities have a fixed price and rents based on how many other railroads or utilities you own.
I have a Game() class that contains three dictionary attributes, all whose key is the land parcel's position on the board from 0-39:
.properties, whose values are a list containing the space's name, buy price, color group and rents (tuple);
.railroads, which consists only of the space name;
.utilities, also containing only the space name.
I did this because at certain points I want to iterate over the appropriate dictionary to see if the player owns other parcels of land in that dictionary; and also because the number of values differs.
Game() also has a tuple called space_types, where each value is a number representing a type of space (property, railroad, utility, luxury tax, GO, etc.). To find out what kind of space_type my player is sitting on:
space_type = space_types[boardposition]
I also have a Player() class with a method buy_property(), which contains a print statement that should say:
"You bought PropertyName for $400."
where PropertyName is the name of the space. But right now I have to use an if/elif/else block like so, which seems ugly:
space_type = Game(space_types[board_position])
if space_type is "property":
# pull PropertyName from Game.properties
elif space_type is "railroad":
# pull PropertyName from Game.railroads
elif space_type is "utility":
# pull PropertyName from Game.utilities
else:
# error, something weird has happened
What I'd like to do is something like this:
dictname = "dictionary to pull from" # based on space_type
PropertyName = Game.dictname # except .dictname would be "dictionary to pull from"
Is it possible in Python to pass the value of a variable as the name of an attribute to be referenced? I will also appreciate someone telling me I'm approaching this fundamentally wrong and suggesting a better way to go about it.
Use the getattr built-in:
PropertyName = getattr(Game, dictname)
http://docs.python.org/2/library/functions.html#getattr
You can use the getattr function:
property_name = getattr(Game, dictname)
How about a dictionary of dictionaries?
D= {"property": Game.properties, "railroad": Game.railroads, "utility": Game.utilities}
space_type = Game(space_types[board_position])
dictname = D[space_type]
I have a list of names and addresses organized in the following format:
Mr and Mrs Jane Doe
Candycane Lane
Magic Meadows, SC
I have several blocks of data written like this, and I want to be able to alphabetize each block by the last name (Doe, in this case). After doing some digging, the best I can reckon is that I need to make a "List of lists" and then use the last name as a key by which to alphabetize the block. However, given by freshness to python and lack of Google skills, the closest I could find was this. I'm confused as to converting each block to a list and then slicing it; I can't seem to find a way to do this and still be able to alphabetize properly. Any and all guidance is greatly appreciated.
If I understood correctly, what you want basically is to sort values by "some computation done on the value", in this case the extracted last name.
For that, use the key keyword argument to .sort() or sorted():
def my_key_function(original_name):
## do something to extract the last name, for example:
try:
return original_name.split(',')[1].strip()
except IndexError:
return original_name
my_sorted_values = sorted(my_original_values, key=my_key_function)
The only requirement is that your "key" function is deterministic, i.e. always return the same output for each given input.
You might also want to sort by last name and then first name: in this case, just return a tuple (last, first): if last si the same for two given items, first will be used to further sort the two.
Update
For your specific case, this function should do the trick:
def my_key_function(original_name):
return original_name.splitlines()[0].split()[-1]
Assuming you already have the data in a list
l = ['Mr and Mrs Jane Smith\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Doe\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Atkins\nCandycane Lane\nMagic Meadows, SC']
You can specify the key to sort on.
l.sort(key=lambda x: x.split('\n')[0].split(' ')[-1])
In this case, get the last word (.split(' ')[-1]) on the first line (.split('\n')[0])
you want to make a new list where each entry is a tuple containing the sort key you want and the whole thing. Sort that list and then get the second component of each entry in the sort:
def get_sort_name (address):
name, address, city = address.split('\n')
return (name.split(' ')[-1] , address) # last item of first line & whole thing as tulle
keyed_list = map (get_sort_name, addresses)
keyed_list.sort()
sorted_addresses = [item[1] for item in keyed_list]
Thi could be more compact using lambdas of course but its better to be readable :)