Adding variables to dictionary, same format - python

I want to make the variables that a user inputs, add to the dictionary. But I want it to be added the way that it currently looks:
bookLogger = [
{'BookName': 'Noise', 'Author': 'Daniel Kahneman', 'Process': 'Reading' },
{'BookName': 'Hunting Party', 'Author': 'Lucy Foley', 'Process': 'Reading'},
{'BookName': 'Superintelligence', 'Author': 'Nick Bostrom', 'Process': 'Not Reading'}
]
The code that I have tried
def AddingBooks():
#User inputs what they want to add tot he library
BName = input("Please enter the book name: ")
BAuthor = input("Enter the books Author: ")
BProcess = input("Are you reading, not reading or haven't started ")
#Want to add this to the bookLogger but in the same format that the
#bookLogger dictionary is in
bookLogger['BookName'] = BName
bookLogger['Author'] = BAuthor
bookLogger['Process'] = BProcess
The error that comes up is list indices must be integers or slices, not str for the bookLogger['BookName'] = BName line.
NOTE:
Not sure how to change it + not sure if that will add it to the bookLogger the way I want it to.

bookLogger is a list that has a dictionary. So You have to push or append the dictionary to the list.
bookLogger = [
{'BookName': 'Noise', 'Author': 'Daniel Kahneman', 'Process': 'Reading' },
{'BookName': 'Hunting Party', 'Author': 'Lucy Foley', 'Process': 'Reading'},
{'BookName': 'Superintelligence', 'Author': 'Nick Bostrom', 'Process': 'Not Reading'}
]
def AddingBooks():
#User inputs what they want to add tot he library
BName = input("Please enter the book name: ")
BAuthor = input("Enter the books Author: ")
BProcess = input("Are you reading, not reading or haven't started ")
#Want to add this to the bookLogger but in the same format that the bookLogger
bookLogger.append({"BookName": BName, "Author": BAuthor, "Process": BProcess})

The error is due to using string as a list index. i.e bookLogger['BookName']. 'BookName' is an index. But you cannot use such string values for the list.
If your logger is
bookLogger = [
{'BookName': 'Noise', 'Author': 'Daniel Kahneman', 'Process': 'Reading' },
{'BookName': 'Hunting Party', 'Author': 'Lucy Foley', 'Process': 'Reading'},
{'BookName': 'Superintelligence', 'Author': 'Nick Bostrom', 'Process': 'Not Reading'}
]
You can write a function this way.
def AddingBooks():
# User inputs what they want to add tot he library
BName = input("Please enter the book name: ")
BAuthor = input("Enter the books Author: ")
BProcess = input("Are you reading, not reading or haven't started ")
# Want to add this to the bookLogger but in the same format that
the
# bookLogger dictionary is in
#first create a dictionary
log = {'BookName': BName,
'Author': BAuthor,
"Process": BProcess}
#bookLogger is a list so you have to append individual log to it
bookLogger.append(log)

Related

Create a dictionary with a fixed set of keys from reading text file in Python

Input:
- A text file that contains 3 lines:
"Thank you
binhnguyen
2010-09-12
I want to say thank you to all of you."
Output:
I want to create a dictionary with fixed keys: 'title', 'name', 'date', 'feedback' that stores 4 lines in the file above respectively.
{'title': 'Thank you', 'name': 'binhnguyen', 'date': '2010-09-12
', 'feedback': 'I want to say thank you to all of you.'}
Thank you so much
You can basically define a list of keys and match them with lines.
Example:
key_list = ["title","name","date","feedback"]
text = [line.replace("\n","").replace("\"","") for line in open("text.txt","r").readlines()]
dictionary = {}
for index in range(len(text)):
dictionary[key_list[index]] = text[index]
print(dictionary)
Output:
{'title': 'Thank you', 'name': 'binhnguyen', 'date': '2010-09-12', 'feedback': 'I want to say thank you to all of you.'}
Given file.txt where the file is and the format is the one described on the question this would be the code:
path = r"./file.txt"
content = open(path, "r").read().replace("\"", "")
lines = content.split("\n")
dict_ = {
'title': lines[0],
'name': lines[1],
'date': lines[2],
'feedback': lines[3]
}
print(dict_)

User input as query for nested dictionary

I have a nested dictionary and instead of a hard coded query to query for ownername John I want to prompt the user for a name and just to test it, I type John upon being prompted and the program crashes with an error that says string indices must be integers.
The below works fine and returns Kitty.
John = { 1: {'name': 'Kitty', 'kind': 'cat'},
2: {'name': 'Ruffle', 'kind': 'dog'},
3: {'name': 'Bobby', 'kind': 'fish'}
}
petownername = John[1]['name']
print(petownername)
This also works fine when I hardcode the owner_name to John and I input the dictionary query with f string.
John = { 1: {'name': 'Kitty', 'kind': 'cat'},
2: {'name': 'Ruffle', 'kind': 'dog'},
3: {'name': 'Bobby', 'kind': 'fish'}
}
owner_name = John
petname = f"{owner_name[1]['name']}"
print(petname)
But as mentioned above when I add new user input it stops working
John = { 1: {'name': 'Kitty', 'kind': 'cat'},
2: {'name': 'Ruffle','kind': 'dog'},
3: {'name': 'Bobby',' kind': 'fish'}
}
owner_name = str(input("Which pet owner do you want to look up?: "))
petname = f"{owner_name[1]['name']}"
print(petname)
I am getting this error:
Which pet owner do you want to look up?: John
Traceback (most recent call last):
File "test3.py", line 9, in <module>
petname = f"{owner_name[1]['name']}"
TypeError: string indices must be integers
So it works fine when I hardcode it and insert it via f string and input is clearly a string. Any idea why it's not working on user prompt?
Do I need to store and refer back to the user prompt in another way perhaps?
It's not working because in the second snippet, owner_name is a dict, while in the third snippet it's a string -- specifically owner_name = 'John' so owner_name[1] == 'o', and 'o'['name'] raises that TypeError. The f-string is irrelevant.
To fix it, use one more level of nested dicts. See How do I create a variable number of variables?.
By the way, instead of a dict with ints as keys, you might want to use a list instead.
pet_owners = {
"John": [
{'name': 'Kitty', 'kind': 'cat'},
{'name': 'Ruffle', 'kind': 'dog'},
{'name': 'Bobby',' kind': 'fish'},
]
}
owner_name = input('Pet owner name: ')
petname = pet_owners[owner_name][0]['name'] # Note the 0 instead of 1
print(petname)
Test run:
Pet owner name: John
Kitty
Also by the way, str(input()) is redundant in Python 3 since input() returns a string.

Making a list of elements from particular parameters in a JSON file

I am doing an assignment for school and I am asked to make a list of names of nobel peace prize winners for a particular year and category.
This is a sample of the JSON file:
[{
'year': '2018',
'category': 'physics',
'overallMotivation': '“for groundbreaking inventions in the field of laser physics”',
'laureates': [{
'id': '960',
'firstname': 'Arthur',
'surname': 'Ashkin',
'motivation': '"for the optical tweezers and their application to biological systems"',
'share': '2'
}, {
'id': '961',
'firstname': 'Gérard',
'surname': 'Mourou',
'motivation': '"for their method of generating high-intensity, ultra-short optical pulses"',
'share': '4'
}, {
'id': '962',
'firstname': 'Donna',
'surname': 'Strickland',
'motivation': '"for their method of generating high-intensity, ultra-short optical pulses"',
'share': '4'
}
]
}, {
'year': '2018',
'category': 'chemistry',
'laureates': [{
'id': '963',
'firstname': 'Frances H.',
'surname': 'Arnold',
'motivation': '"for the directed evolution of enzymes"',
'share': '2'
}, {
'id': '964',
'firstname': 'George P.',
'surname': 'Smith',
'motivation': '"for the phage display of peptides and antibodies"',
'share': '4'
}, {
'id': '965',
'firstname': 'Sir Gregory P.',
'surname': 'Winter',
'motivation': '"for the phage display of peptides and antibodies"',
'share': '4'
}
]
}
]
I am supposed to find a way to find the full names of the people who won for a particular category and year, this is my current code
def get_laureates(dict_prizes, year = "none", category = "none"):
names = []
for row in dict_prizes:
if row["category"] == category:
names.append(row["firstname"] + row['surname'])
return names
year = 2018
category = "peace"
get_laureates(dict_prizes, year = 2018, category = "peace")
and this is the output
TypeError Traceback (most recent call last)
<ipython-input-168-57a2293c1bca> in <module>
11 category = "peace"
12 # test your function here
---> 13 get_laureates(dict_prizes, category = "peace")
<ipython-input-168-57a2293c1bca> in get_laureates(dict_prizes, year, category)
4 names = []
5 for row in dict_prizes:
----> 6 if row["category"] == category and row["year"] == year:
7 names.append(row["firstname"] + row['surname'])
8 return names
TypeError: string indices must be integers
I know there are many errors in this code, I've been unable to convert year into integers, even with the removal of the "years" parameter, I am unable to generate a result with just the category. Any help would be greatly appreciated as I am totally clueless when it comes to JSON (The reading material given to me literally just taught me about dump and load).
Your code generally works which means there is something you are missing on your input data that you didn't post here. I could not reproduce the exact error you are seeing with the data you gave us.
There is one issue that you aren't considering -- you need to loop through the laureates as well and then pull out that winner since that is also a list of dictionaries. I did that below:
dict_prizes = [{'year': '2018', 'category': 'physics', 'overallMotivation': '“for groundbreaking inventions in the field of laser physics”', 'laureates': [{'id': '960', 'firstname': 'Arthur', 'surname': 'Ashkin', 'motivation': '"for the optical tweezers and their application to biological systems"', 'share': '2'}, {'id': '961', 'firstname': 'Gérard', 'surname': 'Mourou', 'motivation': '"for their method of generating high-intensity, ultra-short optical pulses"', 'share': '4'}, {'id': '962', 'firstname': 'Donna', 'surname': 'Strickland', 'motivation': '"for their method of generating high-intensity, ultra-short optical pulses"', 'share': '4'}]}, {'year': '2018', 'category': 'chemistry', 'laureates': [{'id': '963', 'firstname': 'Frances H.', 'surname': 'Arnold', 'motivation': '"for the directed evolution of enzymes"', 'share': '2'}, {'id': '964', 'firstname': 'George P.', 'surname': 'Smith', 'motivation': '"for the phage display of peptides and antibodies"', 'share': '4'}, {'id': '965', 'firstname': 'Sir Gregory P.', 'surname': 'Winter', 'motivation': '"for the phage display of peptides and antibodies"', 'share': '4'}]}]
def get_laureates(dict_prizes, year = "none", category = "none"):
names = []
for row in dict_prizes:
if row["category"] == category:
for winner in row['laureates']: # You need this loop for the inner list of dictionaries
names.append(winner['firstname'] + winner['surname'])
return names
year = 2018
category = "physics"
get_laureates(dict_prizes=dict_prizes, year=2018, category=category)
And got:
>>> get_laureates(dict_prizes=dict_prizes, year=2018, category=category)
['ArthurAshkin', 'GérardMourou', 'DonnaStrickland']
Since you are taking in year you'll need to solve for that part as well which I didn't include since you didn't.
For the provided data you have a list of JSON objects, each of which comprises of
'year': type (string)
'category': type(string)
'overallMotivation': type(string)
'laureates' : type(list) - > this list comprises of more json objects
Since you need the first and the last name of all the author, you need to traverse through both the list. The initial one first to match the "year" and "category" (to match your year kindly change the data-type of year to string), then traverse through the "laureates" and keep on appending row["firstname"] + row['surname']
def get_laureates(dict_prizes, year = None, category = None):
names = []
for category_wise_elements in dict_prizes:
if category_wise_elements["category"] == category and
category_wise_elements['year'] == str(year):
for winner in category_wise_elements['laureates']:
names.append(winner["firstname"] + winner['surname'])
return names
year = 2018
category = "peace"
get_laureates(dict_prizes, year = 2018, category = "peace")
I hope this should help you
Here, I just solved your function by using and if that checks that both year and category match the input you are giving them. That way you can search for all values belonging to that specific criteria. Furthermore, year needs to be treated as string when checking for condition because of how it is expressed within the json file. You can obviously delete the else: line which was made only for validation purposes.
def get_laureates(category,year,json):
names = []
for j in range(len(json)):
if (json[j]['year'] == str(year)) and (json[j]['category'] == category):
for i in range(len(json[j]['laureates'])):
names.append(json[j]['laureates'][i]['firstname'] + ' ' + json[j]['laureates'][i]['surname'])
else:
print('Not found for category '+category+' and year '+str(year))
return names
print(get_laureates(category='physics',year=2018,json=json))
Output:
Not found for category physics and year 2018
['Arthur Ashkin', 'Gérard Mourou', 'Donna Strickland']
Super check for consistency
You can add this right after defining the function:
possibilities = ['physics','chemistry']
for i in range(len(possibilities)):
print(get_laureates(category=possibilities[i],year=2018,json=json))
Output:
Not found for category physics and year 2018
['Arthur Ashkin', 'Gérard Mourou', 'Donna Strickland']
Not found for category chemistry and year 2018
['Frances H. Arnold', 'George P. Smith', 'Sir Gregory P. Winter']
A didactic foolproof solution:
def extract_names(list_names):
# Extraction of fisrtname and surname in "laureates"
return [
"{} {}".format(dicc.get('firstname', ''), dicc.get('surname', '')) for dicc in list_names
]
def get_nobels(list_data, year='', category=''):
# We create the condition of identification of year and category:
bool_condition = lambda _: _.get('year') == str(year) and _.get('category') == str(category)
# Extraction of the names that meet the condition:
elements_select = [
extract_names(dicc.get('laureates', [])) for dicc in list_data if bool_condition(dicc)
][0]
return elements_select
print(get_nobels(list_nobel, 2018, 'chemistry'))
Pythonic Solution:
Using nested list comprehension
Using the membership operator, in
f'{} {}' is an f-string
The function is implemented using PEP 484 -- Type Hints
The caveat being, data is in the form of the list of dicts supplied in the question
def get_name(cat: str, year: str, data: list) -> list:
return [f"{n['firstname']} {n['surname']}" for d in data for n in d['laureates'] if d['category'] == cat and d['year'] == year]
print(get_name('physics', '2018', data))
>>> ['Arthur Ashkin', 'Gérard Mourou', 'Donna Strickland']
Pandas Solution:
pandas
pandas.io.json.json_normalize to get the data into the dataframe.
Indexing and selecting data
import pandas as pd
from pandas.io.json import json_normalize
# create the dataframe
df = json_normalize(data, 'laureates', ['year', 'category'])
# create a column named 'Full Name'
df['Full Name'] = df.firstname.str.cat(df.surname, sep=' ')
print(df)
id firstname surname motivation share year category Full Name
960 Arthur Ashkin "for the optical tweezers and their application to biological systems" 2 2018 physics Arthur Ashkin
961 Gérard Mourou "for their method of generating high-intensity, ultra-short optical pulses" 4 2018 physics Gérard Mourou
962 Donna Strickland "for their method of generating high-intensity, ultra-short optical pulses" 4 2018 physics Donna Strickland
963 Frances H. Arnold "for the directed evolution of enzymes" 2 2018 chemistry Frances H. Arnold
964 George P. Smith "for the phage display of peptides and antibodies" 4 2018 chemistry George P. Smith
965 Sir Gregory P. Winter "for the phage display of peptides and antibodies" 4 2018 chemistry Sir Gregory P. Winter
# search for your criteria
df['Full Name'][(df.category == 'physics') & (df.year == '2018')].tolist()
>>> ['Arthur Ashkin', 'Gérard Mourou', 'Donna Strickland']

How to parse contents from a list of dicts in json using python3 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
My json file :
{
"data": [
{
"features": {
"location": "West Springfield, MA",
"geo_type": "User location",
"screen_name": "JtTatro",
"primary_geo": "West Springfield, MA",
"id": 2158092352,
"tweets": 1,
"name": "Jim Tatro"
},
"user_id": 2158092352
}
,
{
"features": {
"location": "Tijuana, Baja California",
"geo_type": "User location",
"screen_name": "YuitziContreras",
"primary_geo": "Tijuana, Baja California",
"id": 996917180980744193,
"tweets": 1,
"name": "yuitzi contreras"
},
"user_id": 996917180980744193
}
]
}
i am trying to parse the data stored in the features dict. My code so far:
import json
input_file = open ('file.json')
json_array = json.load(input_file)
tweet_list = []
features_list = []
user_list =[]
for item in json_array:
for item2 in json_array[item]:
tweet_list.append(item2)
for features,user in tweet_list:
print(features,user)
the code above returns the dict names : features, user_id. how would it be possible to get the contents of each dict field so that i can pass them to my database?
For example, get location, geo_type etc.
you can parse the features using a list comprehension:
features = [v['features'] for v in json_array['data']]
If any row doesn't have a key called features then v['features'] would throw a KeyError.
To avoid that
features = [v['features'] for v in json_array['data'] if 'features' in v.keys()]
similarly user_list can be constructed.
And finally, tweet_list, which seems functionally to be the zip of features & user_list, can be directly constructed using the list comprehension & dictionary unpacking, like this:
tweet_list = [dict(v['features'], **{'user_id': v['user_id']})
for v in json_array['data']
if 'features' in v.keys() and 'user_id' in v.keys()]
# tweet_list outputs:
[{'geo_type': 'User location',
'id': 2158092352,
'location': 'West Springfield, MA',
'name': 'Jim Tatro',
'primary_geo': 'West Springfield, MA',
'screen_name': 'JtTatro',
'tweets': 1,
'user_id': 2158092352},
{'geo_type': 'User location',
'id': 996917180980744193,
'location': 'Tijuana, Baja California',
'name': 'yuitzi contreras',
'primary_geo': 'Tijuana, Baja California',
'screen_name': 'YuitziContreras',
'tweets': 1,
'user_id': 996917180980744193}]
# features outputs
[{'geo_type': 'User location',
'id': 2158092352,
'location': 'West Springfield, MA',
'name': 'Jim Tatro',
'primary_geo': 'West Springfield, MA',
'screen_name': 'JtTatro',
'tweets': 1},
{'geo_type': 'User location',
'id': 996917180980744193,
'location': 'Tijuana, Baja California',
'name': 'yuitzi contreras',
'primary_geo': 'Tijuana, Baja California',
'screen_name': 'YuitziContreras',
'tweets': 1}]
In JSON, [] represents an array, while {} represents an object. Python parses a JSON object (e.g. {"features": ..., "user_id": ...}) as a dict. You should use .items() method to get key-value pairs from a dict. Iterating over a dict only gives the keys.

Printing dictornary with list order

I have the following code, it is an address book (a list of dictionaries) and a list. The idea is to print the items from the dictionary in the order of the list (since dicts mess up the order of everything). When I run this code, it throws an exception (as shown below). I am not sure what I'm doing wrong as I have tried many different variations and I keep coming back to this wondering why it's not working.
Please help?
addressBook = [
{
'Nickname': 'Jimmy',
'Name': 'James Roberts',
'Address': '2/50 Robe Street',
'Phone': '0273503342'
},
{
'Nickname': 'Bob',
'Name': 'Robert',
'Address': '1 Vivan Street',
'Phone': '067578930'
}
]
addressFields = ['Nickname', 'Name', 'Address', 'Phone']
def listAll(addressBook, addressFields):
for i in addressBook:
for key in addressFields:
print("{0} {1}".format(key, addressBook[i][key]))
print("{0} {1}".format(key, addressBook[i][key]))
TypeError: list indices must be integers, not dict
First, you're missing a ' in the addressBook literal after 'James Roberts. Second, the issue was that you were doing addressBook[i][key] instead of i[key]. i already refers to a dictionary contained in addressBook, so your code was trying to use a list's element as an index to itself.
def listAll(addressBook, addressFields):
for i in addressBook:
for key in addressFields:
print('{} {}'.format(key, i[key]))
Python 3-friendly one-liner:
def listAll(addressBook, addressFields):
print(*('{} {}'.format(j, i[j]) for i in addressBook for j in addressFields), sep='\n')
Alternatively in a single line:
print('\n'.join(element for element in [j+" "+ i[j] for i in addressBook for j in addressFields]
))
#!/usr/bin/python
addressBook = [{'Nickname': 'Jimmy', 'Name': 'James Roberts', 'Address': '2/50 Robe Street', 'Phone': '0273503342'},{'Nickname': 'Bob', 'Name': 'Robert', 'Address': '1 Vivan Street', 'Phone': '067578930'}]
addressFields = ['Nickname', 'Name', 'Address', 'Phone']
def listAll(addressBook, addressFields):
for i in addressBook:
for val in addressFields:
print("{0} {1}".format(val, i[val]))
listAll(addressBook, addressFields)
After posting this question I found the answer.
I converted the addressBook for loop to a range(len(addressBook)) and it worked.
for i in range(len(addressBook)):

Categories