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.
Related
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
I'm trying to write a function, where given names (which are always just First name, Last Name), and the function collects names with the same first name. So far I got this, but I don't know how to proceed to get back the full names in the end.
def same_first_name(people):
for i in range(len(people)):
b=people[i].split()
print(b)
if b[0] == b[0]:
for example :
same_first_name(["Anna Smith", "Barbara Wia", "Anna Brien"])
returns
["Anna Smith", "Anna Brien"]
I'm not 100% clear what you're trying to achieve, but here is a function which accepts a list of names, and makes a dictionary, where the keys are first names, and the values are lists of surnames of people who have the key as their first name:
def same_first_name(people):
split_names = [p.split() for p in people]
first_names_set = set(p[0] for p in split_names)
first_names_dict = {
first_name: [p[1] for p in split_names if p[0] == first_name]
for first_name in first_names_set
}
return first_names_dict
people = ["John Smith", "John Rogers", "Jack Jones", "Jack Smith", "Bill Bong"]
print(same_first_name(people))
Console output:
{'Jack': ['Jones', 'Smith'], 'Bill': ['Bong'], 'John': ['Smith', 'Rogers']}
Given the clarification in your comment, here is a list, where every person is added, who share the same first name with at least one other person in the list:
def same_first_name(people):
split_names = [p.split() for p in people]
first_names_list = [p[0] for p in split_names]
first_names_set = set(first_names_list)
first_name_counts_dict = {
first_name: first_names_list.count(first_name)
for first_name in first_names_set
}
duplicated_first_names = [
p for p in people if first_name_counts_dict[p.split()[0]] >= 2
]
return duplicated_first_names
people = ["John Smith", "John Rogers", "Jack Jones", "Jack Smith", "Bill Bong"]
print(same_first_name(people))
Console output:
['John Smith', 'John Rogers', 'Jack Jones', 'Jack Smith']
I'm having some hard time filtering multiple json datas, I need to know the type of each data and if the type corresponds to a fruit then print the element's fields key, see python example comments for a better explanation.
Here's what the JSON looks like :
#json.items()
{
'type': 'apple',
'fields': {
'protein': '18g',
'glucide': '3%',
}
},
{
'type': 'banana',
'fields': {
'protein': '22g',
'glucide': '8%',
}
},
Here's what I tried to do :
for key, value in json.items(): #access json dict.
if key == 'type': #access 'type' key
if value == 'apple': #check the fruit
if key == 'fields': #ERROR !!! Now I need to access the 'fields' key datas of this same fruit. !!!
print('What a good fruit, be careful on quantity!')
print('more :' + value['protein'] + ', ' + value['glucid'])
if value == 'banana': #if not apple check for bananas
print('One banana each two days keeps you healthy !')
print('more:' + value['protein'] + ', ' + value['glucid'])
Is there a way I can achieve this ?
What you have seems to be a list of dicts.
You then check if keys type and fields exist in the dictionary before checking their value, like this:
for d in data: # d is a dict
if 'type' in d and 'fields' in d:
if d['type'] == 'apple':
... # some print statements
elif d['type'] == 'banana':
... # some more print statements
Based on your representation of the JSON, it appears that is actually a list, not a dictionary. So in order to iterate through it, you could try something like this:
for item in json:
fields = item['fields']
if item['type'] == 'banana':
print('Bananas have {} of protein and {} glucide'.format(fields['protein'], fields['glucide']))
elif item['type'] == 'apple':
print('Apples have {} of protein and {} glucide'.format(fields['protein'], fields['glucide']))
In this code, I wanted to identify a member with his ID. If the ID exist in the dictionary, I would like to print the fullname of this member
iin = input('Enter your ID :')
dict = {'id' : ['aa', 'bb', 'cc'],
'Firstname' : ['Mark', 'Jamal', 'Van'],
'Lastname' : ['Roch', 'borh', 'nilsa']}
for d in dict:
if inn in d:
print('Hello,', dict[inn])
else :
print('Sorry, you are not a member')
The desired result
Enter your ID : aa
Hello, Mark Roch
Thank you for the help
Please check the below code with comments inline.
iin = input('Enter your ID :')
d = {'id' : ['aa', 'bb', 'cc'],
'Firstname' : ['Mark', 'Jamal', 'Van'],
'Lastname' : ['Roch', 'borh', 'nilsa']}
#Get list of IDs
id_list = d['id']
#Check input in list
if iin in id_list:
#Get index of input from ID list
index = id_list.index(iin)
#Get rest of info
fname = d['Firstname'][index]
lname = d['Lastname'][index]
msg = "Hello, " + fname + " " + lname
print msg
else:
print 'Sorry, you are not a member'
Output :
C:\Users\dinesh_pundkar\Desktop>python b.py
Enter your ID :"aa"
Hello, Mark Roch
C:\Users\dinesh_pundkar\Desktop>python b.py
Enter your ID :"asd"
Sorry, you are not a member
C:\Users\dinesh_pundkar\Desktop>
There's no need to loop over all the items in the dictionary; it would be silly to look for an id in the Firstname and Lastname fields. (And this could produce incorrect results if the entered id happens to be a substring of someone's name.)
What you want is to check if the given id is present in the id list, and if so, use that list position to print the corresponding first and last names:
if iin in dict['id']:
index = dict['id'].index(iin)
print('Hello, %s %s' % (dict['Firstname'][index], dict['Lastname'][index]))
else :
print('Sorry, you are not a member')
Some suggestions:
It might be easier if you arranged your data as a list of dicts each containing a single member, like so:
members = [
{'id': 'aa', 'Firstname': 'Mark', 'Lastname': 'Roch'},
{'id': 'bb', 'Firstname': 'Jamal', 'Lastname': 'borh'},
{'id': 'cc', 'Firstname': 'Van', 'Lastname': 'nilsa'},
]
Don't name your dictionary dict, as that conflicts with a built-in function name.
Building on previous posts
iin = input('Enter your ID :')
dict = {'id' : ['aa', 'bb', 'cc'],
'Firstname' : ['Mark', 'Jamal', 'Van'],
'Lastname' : ['Roch', 'borh', 'nilsa']}
try:
i = dict['id'].index(iin)
print('Hello {0} {1}'.format(dict['Firstname'][i], dict['Lastname'][i])
except ValueError:
print('Sorry, you are not a member')
NOTE: you cannot name a dictionary dict because it conflicts with a keyword.
The working version of the code should be:
my_dict = {'id' : ['aa', 'bb', 'cc'],
'Firstname' : ['Mark', 'Jamal', 'Van'],
'Lastname' : ['Roch', 'borh', 'nilsa']}
iin = input('Enter your ID :')
# Enter your ID :"bb"
try:
my_id = my_dict['id'].index(iin)
print my_dict['Firstname'][my_id], ', ', my_dict['Lastname'][my_id]
except ValueError:
print 'Sorry, you are not a member'
# Jamal , borh
Exlaination/Issues with your code:
for d in dict means for d in dict.keys() which will return ['id', 'FirstName', 'LastName'. In order to iterate over id, you should be doing for d in dict['id']. In fact, iterating over the list itself is not required. To get index of element in ;list, you may simply use list.index(element) function
dict is the built-in class in python. You should never use the keywords
You dictionary structure is itself not correct. By definition, dict means collections of objects and object means similar entities. In this case, Person. Since id is supposed by unique, in am making nested dict with key as id (you may also use list of dict):
{'aa': {'Firstname' : 'Mark',
'Lastname' : 'Roch'},
'bb': {'Firstname' : 'Jamal',
'Lastname' : 'borh'},
'cc': {'Firstname' : 'Van',
'Lastname' : 'nilsa'},
}
So basically I need to parse a name and find the following info:
First Name
First Initial (if employee has initials for a first name like D.J., use both initials)
Last Name (include if employee has a suffix such as Jr. or III.)
So here's the interface I'm working with:
Input:
names = ["D.J. Richies III", "John Doe", "A.J. Hardie Jr."]
for name in names:
print parse_name(name)
Expected Output:
{'FirstName': 'D.J.', 'FirstInitial': 'D.J.', 'LastName': 'Richies III' }
{'FirstName': 'John', 'FirstInitial': 'J.', 'LastName': 'Doe' }
{'FirstName': 'A.J.', 'FirstInitial': 'A.J.', 'LastName': 'Hardie Jr.' }
Not really good at Regex, and actually that's probably overkill for this. I'm just guessing:
if name[1] == ".": # we have a name like D.J.?
I found this library quite useful for parsing names. https://code.google.com/p/python-nameparser/
It can also deal with names that are formatted Lastname, Firstname.
There is no general solution and solution will depend on the constraints you put. For the specs you have given here is a simple solution which gives exactly what you want
def parse_name(name):
fl = name.split()
first_name = fl[0]
last_name = ' '.join(fl[1:])
if "." in first_name:
first_initial = first_name
else:
first_initial = first_name[0]+"."
return {'FirstName':first_name, 'FirstInitial':first_initial, 'LastName':last_name}
names = ["D.J. Richies III", "John Doe", "A.J. Hardie Jr."]
for name in names:
print parse_name(name)
output:
{'LastName': 'Richies III', 'FirstInitial': 'D.J.', 'FirstName': 'D.J.'}
{'LastName': 'Doe', 'FirstInitial': 'J.', 'FirstName': 'John'}
{'LastName': 'Hardie Jr.', 'FirstInitial': 'A.J.', 'FirstName': 'A.J.'}
Well, for your simple example names, you can do something like this.
# This separates the first and last names
name = name.partition(" ")
firstName = name[0]
# now figure out the first initial
# we're assuming that if it has a dot it's an initialized name,
# but this may not hold in general
if "." in firstName:
firstInitial = firstName
else:
firstInitial = firstName[0] + "."
lastName = name[2]
return {"FirstName":firstName, "FirstInitial":firstInitial, "LastName": lastName}
I haven't tested it, but a function like that should do the job on the input example you provided.
This is basically the same solution as the one Anurag Uniyal provided, only a little more compact:
import re
def parse_name(name):
first_name, last_name = name.split(' ', 1)
first_initial = re.search("^[A-Z.]+", first_name).group()
if not first_initial.endswith("."):
first_initial += "."
return {"FirstName": first_name,
"FirstInitial": first_initial,
"LastName": last_name}