zyDE 9.15.1: Nested dictionaries example: Music library - python

So, I wanted to answer this question for those who could not answer this question.
I wanted to help, so here is my answer since it was a little hard for me.
If you can think of anything better, let everyone know.
zyDE 9.15.1: Nested dictionaries example: Music library.
The following example demonstrates a program that uses 3 levels of nested dictionaries to create a simple music library.
The following program uses nested dictionaries to store a small music library. Extend the program such that a user can add artists, albums, and songs to the library. First, add a command that adds an artist name to the music dictionary. Then add commands for adding albums and songs. Take care to check that an artist exists in the dictionary before adding an album, and that an album exists before adding a song.
Answer:
music = {
'Pink Floyd': {
'The Dark Side of the Moon': {
'songs': [ 'Speak to Me', 'Breathe', 'On the Run', 'Money'],
'year': 1973,
'platinum': True
},
'The Wall': {
'songs': [ 'Another Brick in the Wall', 'Mother', 'Hey you'],
'year': 1979,
'platinum': True
}
},
'Justin Bieber': {
'My World':{
'songs': ['One Time', 'Bigger', 'Love Me'],
'year': 2010,
'platinum': True
}
}
}
prompt = ("1. Enter artist information\n"
"2. Exit\n")
command = ''
while command != '2':
command = input(prompt).lower()
if command == '1':
artist = input('Artist: ')
if artist in music.keys():
print('That artist already exists. Please try again.')
artist = input('Artist: ')
album = input('Album: ')
for albums in music.values():
if album in albums:
print('That album already exists. Please try again')
album = input('Album: ')
songs = input('Song: ').split()
music[artist] = {album: {'songs': songs}}
else:
break
print(music)

Maybe you can try this way:
prompt = ("1. Enter artist information\n"
"2. Exit\n")
command = ''
while command != '2':
command = input(prompt).lower()
if command == '1':
artist = input('Artist: ')
album = input('Album: ')
songs = input('Song: ').split()
if artist in music.keys():
print(music[artist].keys())
if album in music[artist].keys():
music[artist][album]["songs"] += songs
else:
music[artist].update({album: {}})
music[artist][album].update({"songs": songs})
else:
music.update({artist: {}})
music[artist].update({album: {}})
music[artist][album].update({"songs": songs})
print('\n', music)

Related

Function not Printing two separate print statements

I am new to personal projects and am working on a library book management system through the python terminal.
I'm running into an issue that has had been stuck for a while.
I'm trying to get my code to print out into the console
------ Main Menu ------
All Books
Check In
Check Out
Look Up
But instead it just gives me over and over again just "Choose Option". I'm not sure what I'm doing wrong as I've tried iterating a bunch of times over but I can't find the resolution.
Source Code:
Terminal Output:
In the future try pasting your code directly into your question rather than as an image.
Regardless, try moving the line starting with option i.e.:
option = input("Choose options: ")
into inside the mainMenu
function (main_menu in the attempted reconstruction of your attempt below):
#
#
# Print menu
# Menu will include a list if menu options
# Create a main menu function that will control the main menu
# Then call functions as they are requested by the user
# Will require a dictionary using id's as the key and book info as values
#
#
import pprint
import os
# Books in the System
books = [
{"ID": 100001, "title": "Meditations", "author": "Marcus Aurelius", "year": 180},
{"ID": 100002, "title": "To Kill a Mockingbird", "author": "Harper Lee", "year": 1960},
{"ID": 100003, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "year": 1925},
{"ID": 100004, "title": "Don Quixote", "author": "Miguel de Cervantes", "year": 1615},
{"ID": 100005, "title": "The Little Prince", "author": "Antoine de Saint-Exupery", "year": 180}
]
menu = " ------ Main Menu ------ \n\n 1. All Books \n 2. Check In \n 3. Check Out \n 4. Look Up \n"
def menu1():
pprint.pprint(books)
option1 = input("Type 0 to go back: ")
if option1 == "0":
os.system("clear")
return main_menu()
def main_menu():
print(menu)
option = input("Choose option: ")
if option == "1":
os.system("clear")
return menu1()
if __name__ == '__main__':
main_menu()
Example Usage:
------ Main Menu ------
1. All Books
2. Check In
3. Check Out
4. Look Up
Choose option: 1
[{'ID': 100001,
'author': 'Marcus Aurelius',
'title': 'Meditations',
'year': 180},
{'ID': 100002,
'author': 'Harper Lee',
'title': 'To Kill a Mockingbird',
'year': 1960},
{'ID': 100003,
'author': 'F. Scott Fitzgerald',
'title': 'The Great Gatsby',
'year': 1925},
{'ID': 100004,
'author': 'Miguel de Cervantes',
'title': 'Don Quixote',
'year': 1615},
{'ID': 100005,
'author': 'Antoine de Saint-Exupery',
'title': 'The Little Prince',
'year': 180}]

Im stuck on in-completed code on printing variable and list

This is the code I'm stuck on. For example, if I input in Horror, Action then the output would be
Anabelle=["Horror", "Triller"]
Avengers=["Action", "Fantasy", "Sci-fi"]
Scooby_doo=["Comedy", "Horror"]
Brooklyn_99=["Action", "Comedy"]
Fast_Furious=["Action"]
Conjuring=["Horror"]
Spider_Man=["Action", "Fantasy"]
basically, printing the variable and the list that contains the user input. also if possible, I need to use lists, also don't change the code too much and add comments for each section
my_list= ["Horror, Action, Comedy, Thriller, Mystery, Fantasy, Sci-fi, Romance,
Drama, Dystopian"]
print("All Available Genres " + str(my_list))
Anabelle=["Horror", "Triller"]
Criminal_Minds=["Mystery", "Drama"]
Avengers=["Action", "Fantasy", "Sci-fi"]
Scooby_doo=["Comedy", "Horror"]
Brooklyn_99=["Action", "Comedy" ]
The_fault_in_our_stars=["Romance", "Drama"]
The_tomorrow_war=["Drama", "Sci-Fi"]
Maze_Runner=["Drama", "Dystopian", "Thriller"]
Hunger_Game=["Dystopian", "Sci-Fi", "Thriller"]
Harry_Potter=["Mystery", "Fantasy"]
Fast_Furious=["Action"]
Conjuring=["Horror"]
Fantastic_Beast=["Fantasy"]
Parasite=["Comedy", "Thriller"]
Space_between_us=["Romance"]
Murder_Mystery=["Romance", "Mystery"]
The_Purge=["Dystopian", "Thriller"]
Spider_Man=["Action", "Fantasy"]
variable_strings=['Anabelle', 'Criminal_Minds', 'Avengers', 'Scooby_doo', 'Brooklyn_99', 'The_fault_in_our_stars', 'The_tomorrow_war', 'Maze_Runner', 'Hunger_Game', 'Harry_Potter', 'Fast_Furious', 'Conjuring', 'Fantastic_Beast', 'Parasite', 'Space_between_us', 'Murder_Mystery', 'The_Purge', 'Spider_Man']
newlist = [Anabelle, Criminal_Minds, Avengers, Scooby_doo, Brooklyn_99, The_fault_in_our_stars, The_tomorrow_war, Maze_Runner, Hunger_Game, Harry_Potter, Fast_Furious, Conjuring, Fantastic_Beast, Parasite, Space_between_us, Murder_Mystery, The_Purge, Spider_Man]
user_genre = (input("What movie/show genre do you like to watch?: "))
user_genre = user_genre.split(", ") if ", " in user_genre else user_genre.split(",")
This is quite ugly, but I've tried not to change it too much:
my_list= ["Horror", "Action", "Comedy", "Thriller", "Mystery", "Fantasy", "Sci-fi", "Romance", "Drama", "Dystopian"]
print("All Available Genres " + str(my_list))
movies = {
"Anabelle": ["Horror", "Triller"],
"Criminal_Minds": ["Mystery", "Drama"],
"Avengers": ["Action", "Fantasy", "Sci-fi"],
"Scooby_doo": ["Comedy", "Horror"],
"Brooklyn_99": ["Action", "Comedy" ],
"The_fault_in_our_stars": ["Romance", "Drama"],
"The_tomorrow_war": ["Drama", "Sci-Fi"],
"Maze_Runner": ["Drama", "Dystopian", "Thriller"],
"Hunger_Game": ["Dystopian", "Sci-Fi", "Thriller"],
"Harry_Potter": ["Mystery", "Fantasy"],
"Fast_Furious": ["Action"],
"Conjuring": ["Horror"],
"Fantastic_Beast": ["Fantasy"],
"Parasite": ["Comedy", "Thriller"],
"Space_between_us": ["Romance"],
"Murder_Mystery": ["Romance", "Mystery"],
"The_Purge": ["Dystopian", "Thriller"],
"Spider_Man": ["Action", "Fantasy"],
}
user_genres = (input("What movie/show genre do you like to watch?: "))
user_genres = user_genres.split(", ") if ", " in user_genres else user_genres.split(",")
for (movie, genres) in movies.items():
toPrint = False
for genre in genres:
if genre in user_genres:
toPrint = True
if toPrint:
print(movie + " [" + ", ".join(genres) + "]")
I'm not 100% sure if this is what you are asking for but here is some code that
-iterates through movies
-checks if genre is in each movie''
if it is, prints movie name.
Simply add this to the end of your code
#Splitting user request
user_genre_s = user_genre.split(", ") if ", " in user_genre else user_genre.split(",")
movies_found = 0
print(f"The following movies were found for genres {user_genre}:")
for movie in newlist:
#testing if value was found in each movie's list
for genre in user_genre_s:
if genre in movie:
print(variable_strings[newlist.index(movie)].replace("_"," "))#printing movie name if found, replacing underscores with spaces to make it look nicer
movies_found += 1
if movies_found == 0:
print(":( no match was found")#Telling user if none are found.
However you may want to lower() all of the genres as users may not enter capitals

allowing the user to input two parameters

i want to allow the user to be able to type {misc} of {nation} and specific information will be displayed based on the input. i have tired several different ways but seem to never find a way to make it work. any help is appreciated thanks!
(Sorry about title didnt really know what to title it)
def part1():
txt = "{} of {}"
info = input('''What do you want to know?: ''')
if info == "{} of {}":
print(txt.format(misc.get(info), nations.get(info)))
else:
print("i dont know what your talking about")
nations = {
'fiji': {
'location': 'Oceana',
'capital_city': 'Suva'},
'france': {
'location': 'Europe',
'capital_city': 'Paris'},
}
misc = {'population': {'fiji': '847,706',
'france': '60,495,540'},
'location': {'fiji': 'Oceana',
'france': 'Europe'},
}
part1()
Not sure exactly what you're trying to do, but there are a few issues with your code, try something like this:
def part1():
txt = "{} of {}"
info = input('''What do you want to know?: ''')
if ' of ' in info:
params = info.split(' of ')
else:
print("i dont know what your talking about")
return
print(params[0])
print(misc.get(params[0]).get(params[1]))
nations = {
'fiji': {
'location': 'Oceana',
'capital_city': 'Suva'},
'france': {
'location': 'Europe',
'capital_city': 'Paris'},
}
misc = {'population': {'fiji': '847,706',
'france': '60,495,540'},
'location': {'fiji': 'Oceana',
'france': 'Europe'},
}
part1()
Currently with this code there isnt really a way to know which object you're targeting (nations or misc). To remedy this I would ask the user an initial question to determine which type of info they want.
Additional improvements could be checking the data you're getting from the dictionaries. In the case you get nothing from the dictionaries (.get returns None) you could notify the user the info you have available).
A quick and dirty way to do this if you are not using much data, is to just put the info directly into the if statements and call the function. For instance:
def part1():
info = input("What do you want to know?: ")
if info == "location of fiji":
print("Oceana:")
elif info == "capital_city of fiji":
print("Suva")
elif info == "location of France":
print("Europe")
elif info == "capital_city of France":
print("Paris")
else:
print("i dont know what your talking about")
part1()
If you are using a lot of data points, then it is probably better to have a list/database like you have though. Here's the quick and dirty fix if you want it though.
(Also, if you use this method, you can convert the user input string into all lowercase using .lower I believe. This way, capitalization does not matter when inputting).
A good way to do this would be if else/elif statements that way the program can check for multiple inputs rather then trying to check for 2 different inputs at once.
Viktor Basharkevich has pretty much the right idea on what to do
You could also try a split method
input().split(x, y)
x, y = input("What do you want to know?").split()
This might work
Or you could try a list

Saving list data in python

I am wondering how I can save whatever I added to a list when I close a python file. For example, in this "my contact" program that I wrote below, if I add information about 'Jane Doe', what could I do so that next time I open up the same file, Jane Doe still exists.
def main():
myBook = Book([{"name": 'John Doe', "phone": '123-456-7890', "address": '1000 Constitution Ave'}])
class Book:
def __init__(self, peoples):
self.peoples = peoples
self.main_menu()
def main_menu(self):
print('Main Menu')
print('1. Display Contact Names')
print('2. Search For Contacts')
print('3. Edit Contact')
print('4. New Contact')
print('5. Remove Contact')
print('6. Exit')
self.selection = input('Enter a # form the menu: ')
if (self.selection == "1"):
self.display_names()
if (self.selection == "2"):
self.search()
if (self.selection == "3"):
self.edit()
if (self.selection == "4"):
self.new()
if (self.selection == "5"):
self.delete()
if (self.selection == "6"):
self.end()
def display_names(self):
for people in self.peoples:
print("Name: " + people["name"])
self.main_menu()
def search(self):
searchname = input('What is the name of your contact: ')
for index in range(len(self.peoples)):
if (self.peoples[index]["name"] == searchname):
print("Name: " + self.peoples[index]["name"])
print("Address: " + self.peoples[index]["address"])
print("Phone: " + self.peoples[index]["phone"])
self.main_menu()
def edit(self):
searchname = input('What is the name of the contact that you want to edit: ')
for index in range(len(self.peoples)):
if (self.peoples[index]["name"] == searchname):
self.peoples.pop(index)
name = input('What is your name: ')
address = input('What is your address: ')
phone = input('What is your phone number: ')
self.peoples.append({"name": name, "phone": phone, "address": address})
self.main_menu()
def new(self):
name = input('What is your name: ')
address = input('What is your address: ')
phone = input('What is your phone number: ')
self.peoples.append({"name": name, "phone": phone, "address": address})
self.main_menu()
def delete(self):
searchname = input('What is the name of the contact that you want to delete: ')
for index in reversed(range(len(self.peoples))):
if (self.peoples[index]["name"] == searchname):
self.peoples.pop(index)
print(searchname, 'has been removed')
self.main_menu()
def end(self):
print('Thank you for using the contact book, have a nice day')
print('Copyright Carson147 2019©, All Rights Reserved')
main()
Use a module from the Data Persistence section of the standard library, or save it as json, or as a csv file.
You just convert your list to array inside in function .
np.save('path/to/save', np.array(your_list))
to load :
arr=np.load(''path/to/save.npy').tolist()
I hope it will be helpful
There are innumerable kinds of serialization options, but a time-tested favorite is JSON. JavaScript Object Notation looks like:
[
"this",
"is",
"a",
"list",
"of",
"strings",
"with",
"a",
{
"dictionary": "of",
"values": 4,
"an": "example"
},
"can strings be single-quoted?",
false,
"can objects nest?",
{
"I": {
"Think": {
"They": "can"
}
}
}
]
JSON is widely used, and the Python stdlib has a method of converting objects to and from JSON in the json package.
>>> import json
>>> data = ['a', 'list', 'full', 'of', 'entries']
>>> json.dumps(data) # dumps will dump to string
["a", "list", "full", "of", "entries"]
You can then save your Book data to json before the program shuts down, and read from json after it starts up.
# at the top
import json
from pathlib import Path
# at the bottom of your program:
if __name__ == '__main__':
persistence = Path('book.json')
if persistence.exists():
with persistence.open() as f:
data = json.load(f)
else:
data = [{"name": 'John Doe', "phone": '123-456-7890', "address": '1000 Constitution Ave'}]
book = Book(data)
with persistence.open('w') as f:
json.dump(f, indent=4)
There is no way you can do that without any external modules, such as numpy or pickle. Using pickle, you can do this: (I am assuming you want to save the myBook variable)
import pickle
pickle.dump(myBook, open("foo.bar", "wb")) #where foo is name of file and bar is extension
#also wb is saving type, you can find documentation online
To load:
pickle.load(myBook, open("foo.bar", "rb"))
EDIT:
I was wrong in my first statement. There is a way to save without importing a module. Here is how:
myBook.save(foo.bar) #foo is file name and bar is extention
To load:
myBook=open(foo.bar)
As evinced by the many other answers, there are many ways to do this, but I thought it was helpful to have a example.
By changing the top of your file as so, you can use the shelve module.
There are a variety of other things you can fix in your code if you are curious, you could try https://codereview.stackexchange.com/ if you want more feedback.
import shelve
def main():
default = [
{'name': 'John Doe', 'phone': '123-456-7890',
'address': '1000 Constitution Ave'}
]
with Book('foo', default=default) as myBook:
myBook.main_menu()
class Book:
def __init__(self, filename, default=None):
if default is None:
default = []
self._db = shelve.open(filename)
self.people = self._db.setdefault('people', default)
def __enter__(self):
return self
def __exit__(self):
self._db['people'] = self.people
self._db.close()

How do I work with a nested dictionary's name?

I'm writing a program using dictionaries nested within a list. I want to print the name of each dictionary when looping through the list, but don't know how to do that without calling the entire contents of the dictionary. Here is my code:
sam = {
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
}
dave = {
'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}
people = [sam, dave]
for person in people:
for key, value in sorted(person.items()):
print( #person's name +
"'s favorite " + key + " is " + value + ".")
Here is the output:
's favorite country is mexico.
's favorite food is tortas.
's favorite song is Dream On.
's favorite country is USA.
's favorite food is spaghetti.
's favorite song is Sweet Home Alabama.
Everything works, I just need the names of my dictionaries to print. What's the solution?
The (more) correct way of doing this is to construct a dict of dicts instead, such as:
people = {'sam': {'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
},
'dave': {'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}
}
Then you can simply do the following:
for name, person in people.items():
for key, value in sorted(person.items()):
print(name + "'s favorite " + key + " is " + value + ".")
This will print the following:
dave's favorite country is USA.
dave's favorite food is spaghetti.
dave's favorite song is Sweet Home Alabama.
sam's favorite country is mexico.
sam's favorite food is tortas.
sam's favorite song is Dream On.
As a side note, it is more readable to use string formatting in your print statement:
print("{0}'s favorite {1} is {2}".format(name, key, value))
what you are basically trying to do is printing the name of a variable. Of course, this is not reccomended. If you really want to do this, you should take a look at this post:
How can you print a variable name in python?
What i would do, is to store the name of the dictionary inside of the lists. You could do this by changing 'people = [sam, dave]' to 'people = [["sam", sam], ["dave", dave]]'. This way, person[0] is the name of the person, and person[1] contains the information.
The simplest way is to store the name as a string that maps to the matching variable identifier:
people = {'sam':sam, 'dave':dave}
for name, person in people.items():
for key, value in sorted(person.items()):
print(name + "'s favorite " + key + " is " + value + ".")
If you really don't like the idea of typing each name twice, you could 'inline' the dictionaries:
people = {
'sam':{
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
},
'dave':{
'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}
}
Finally, if you can rely on those variables being in the global namespace and are more concerned with just making it work than purity of practice, you can find them this way:
people = ['sam', 'dave']
for name in people:
person = globals()[name]
for key, value in sorted(person.items()):
print(name + "'s favorite " + key + " is " + value + ".")
Values in a list aren't really variables any more. They aren't referred to by a name in some namespace, but by an integer indicating their offsets from the front of the list (0, 1, ...).
If you want to associate each dict of data with some name, you have to do it explicitly. There are two general options, depending on what's responsible for tracking the name: the collection of people, or each person in the collection.
The first and easiest is the collections.OrderedDict --- unlike the normal dict, it will preserve the order of the people in your list.
from collections import OrderedDict
sam = {
'food': 'tortas',
'country': 'Mexico',
'song': 'Dream On',
}
dave = {
'food': 'spaghetti',
'country': 'USA',
'song': 'Sweet Home Alabama',
}
# The OrderedDict stores each person's name.
people = OrderedDict([('Sam', sam), ('Dave', dave)])
for name, data in people.items():
# Name is a key in the OrderedDict.
print('Name: ' + name)
for key, value in sorted(data.items()):
print(' {0}: {1}'.format(key.title(), value))
Alternatively, you can store each person's name in his or her own dict... assuming you're allowed to change the contents of those dictionaries. (Also, you wouldn't want to add anything to the data dictionary that would require you to change / update the data more than you already do. Since most people change their favorite food or song much more often than they change their name, this is probably safe.)
sam = {
# Each dict has a new key: 'name'.
'name': 'Sam',
'food': 'tortas',
'country': 'Mexico',
'song': 'Dream On',
}
dave = {
'name': 'Dave',
'food': 'spaghetti',
'country': 'USA',
'song': 'Sweet Home Alabama',
}
people = [sam, dave]
for data in people:
# Name is a value in the dict.
print('Name: ' + data['name'])
for key, value in sorted(data.items()):
# Have to avoid printing the name again.
if 'name' != key:
print(' {0}: {1}'.format(key.title(), value))
Note that how you print the data depends on whether you store the name in the collection (OrderedDict variant), or in each person's dict (list variant).
Thanks for the great input. This program is for a practice example in "Python Crash Course" by Eric Matthes, so the inefficient "dictionaries inside list" format is intentional. That said, I got a lot out of your comments, and altered my code to get the desired output:
sam = {
#Added a 'name' key-value pair.
'name' : 'sam',
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
}
dave = {
'name' : 'dave',
'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}
people = [sam, dave]
for person in people:
for key, value in sorted(person.items()):
#Added if statement to prevent printing the name.
if key != 'name':
print(person['name'].title() + "'s favorite " + key + " is " + value + ".")
#Added a blank line at the end of each for loop.
print('\n')
Here is the output:
Sam's favorite country is mexico.
Sam's favorite food is tortas.
Sam's favorite song is Dream On.
Dave's favorite country is USA.
Dave's favorite food is spaghetti.
Dave's favorite song is Sweet Home Alabama.
Thanks again, all who provided insightful answers.

Categories

Resources