How to do a length check using nested dictionary - python

I'm trying to make a length check on my dictionary as a form of simple validation. For example I'm trying to put a limit of number of players that can join a specific team which is a nested dictionary. Here's what I've done so far
teamS = {
"Team 1": {"Team Ahab":["Venom,Paz,Chico,Kaz,Miguel"],"Score":[],"Event":[]},
"Team 2": {"Team Ishmael":[],"Score":[],"Event":[]},
"Team 3": {"Team Miller":[],"Score":[],"Event":[]},
"Team 4": {"Team Raiden":[],"Score":[],"Event":[]}}
if len(teamS["Team 1"]["Team Ahab"]) > 5:
teamS["Team 1"]["Team Ahab"].pop(5)
print("This team is full so please join another one instead")
My ideal output would be like this
teamchoice = input("What team do you want to join) ("Team Ahab")
print("This team is full so please join another one)

This is poor design. You have two keys that make it harder for you to work. If you want to key by team name, that's fine, but don't make a redundant team ID. Just use a dictionary where the team is the key and the roster is a list of names, with built-in len.
teams = {
"Ahab": {
"roster": ["Venom", "Paz", "Chico", "Kaz", "Miguel"],
"Score": [],
"Event": []
},
"Ishmael" : {
"roster:[],
"Score": [],
"Event": []
},
...
}
Simply look up the given team; let's just call that pref_team.
if len(teamS[pref_team][roster]) >= 5:
# reject membership
That should be enough to get you moving.

Based on your code, to get the len of the team, you should do something like this:
print(len(str(teamS["Team 1"]["Team Ahab"]).split(",")))
You need to get the Dictionary inside the Team number, and then, the list of members is just an string separated by commas

Related

Create dictionary using JSON data

I have a JSON file that has movie data in it. I want to create a dictionary that has the movie title as the key and a count of how many actors are in that movie as the value. An example from the JSON file is below:
{
"title": "Marie Antoinette",
"year": "2006",
"genre": "Drama",
"summary": "Based on Antonia Fraser's book about the ill-fated Archduchess of Austria and later Queen of France, 'Marie Antoinette' tells the story of the most misunderstood and abused woman in history, from her birth in Imperial Austria to her later life in France.",
"country": "USA",
"director": {
"last_name": "Coppola",
"first_name": "Sofia",
"birth_date": "1971"
},
"actors": [
{
"first_name": "Kirsten",
"last_name": "Dunst",
"birth_date": "1982",
"role": "Marie Antoinette"
},
{
"first_name": "Jason",
"last_name": "Schwartzman",
"birth_date": "1980",
"role": "Louis XVI"
}
]
}
I have the following but it's counting all of the actors from all of the movies instead of each movie and the number of actors per movie. I'm not sure how to do this correctly as I'm newer to Python so help would be great.
import json
def actor_count(json_data):
with open("movies_db.json", 'r') as file:
data = json.load(file)
for t in data:
title = [t['title'] for t in data]
for element in data:
for actor in element['actors']:
rolee = [actor['role'] for movie in data for actor in movie['actors']]
len_role = [len(role)]
newD = dict(zip(title, len_role))
print(newD)
json_data = open('movies_db.json')
actor_count(json_data)
You show json that only contains a dictionary, yet you seem to process it as if it were a list of dictionaries with the structure you have shown. Pending clarification, I am answering here as if the latter is true -- you have a list of dictionaries, since you would be asking a different question about a different error if this was not the case.
In your function, each element of data is a dictionary that contains the information for a single movie. To get a dict correlating the title to the count of actors in this movie, you just need to access the "title" key and the length of the "actors" key for each element.
def actor_count(json_data):
movie_actors = {}
for movie in json_data:
title = movie["title"]
num_actors = len(movie["actors"])
movie_actors[title] = num_actors
return movie_actors
Alternatively, use a dictionary comprehension to build this dictionary:
def actor_count(json_data):
movie_actors = {movie["title"]: len(movie["actors"]) movie in json_data}
return movie_actors
Now, load your json file once, and use that when you call actors_count. This will return a dictionary mapping each movie title to the number of actors.
with open("movies_db.json", 'r') as file:
data = json.load(file)
actors_count(data)
Note that loading the json file again in the function is unnecessary, since you already did it before calling the function, and are passing the parsed object to the function.
If you want to keep your current logic of using list comprehensions, and then zipping the resultant lists to create a dict, that is also possible although slightly less efficient. There are significant changes you will need to make:
def actor_count(json_data):
title = [t['title'] for t in json_data]
n_actors = [len(t['actors'] for t in json_data)]
newD = dict(zip(title, n_actors))
return newD
As before, no need to read the file again in the function
You're already looping over all elements in json_data as part of the list comprehension, so no need for another loop outside this.
You can get the number of actors simply by len(t['actors'])
You seem to have misconceptions about how list comprehensions and loops work. A list comprehension is a self-contained loop that builds a list. If you have a list comprehension, there's usually no need to surround it by the same for ... in ... statement that already exists in the comprehension.
def actor_count(json_data):
newD = dict()
with open("movies_db.json", 'r') as file:
data = json.load(file)
for t in data:
if t == 'title':
title_ = json_data[t]
newD[ title_ ] = 0
if t == 'actors':
newD[ title_ ] = len(json_data[t])
print(newD)
Output:
{'Marie Antoinette': 2}

Why is this dictionary comprehension for list of dictionaries not returning values?

I am iterating over a list of dictionaries in a list formatted as follows (each dictionary relates to one item of clothing, I have only listed the first:
new_products = [{'{"uniq_id": "1234", "sku": "abcdefgh", "name": "Levis skinny jeans", '
'"list_price": "75.00", "sale_price": "55.00", "category": "womens"}'}]
def find_product(dictionary, uniqid):
if 'uniq_id' in dictionary:
if ['uniq_id'] == uniqid:
return(keys, values in dictionary)
print(find_product(new_products, '1234'))
This is returning
None
The reason for the if statement in there is that not every product has a value for uniq_id so I was getting a key error on an earlier version of my code.
Your dictionary definition is quite unclear.
Assuming that you have given a list of dictionaries of size 1, it should be something like this:
new_products = [{"uniq_id": "1234", "sku": "abcdefgh", "name": "Levis skinny jeans", "list_price": "75.00", "sale_price": "55.00", "category": "womens"}]
def find_product(list_of_dicts, uniqid):
for dictionary in list_of_dicts:
if 'uniq_id' in dictionary:
if dictionary['uniq_id'] == uniqid:
return dictionary
print(find_product(new_products, '1234'))
You are using something like this:
new_products = [{'{ "some" : "stuff" }'}]
This is a list (the outer []) containing a set (the {})
{'{ "some" : "stuff" }'}
Note {1} is a set containing the number 1. Though it uses the curly braces it isn't a dictionary.
Your set contains a string:
'{ "some" : "stuff" }'
If I ask if 'some' is in this, I get True back, but if I ask for this string's keys there are no keys.
Make your new_products a list containing a dictionary (not a set), and don't put the payload in a string:
new_products = [{"uniq_id": "1234",
"sku": "abcdefgh",
"name": "Levis skinny jeans",
"list_price": "75.00",
"sale_price": "55.00",
"category": "womens"}]
Then loop over the dictionaries in the list in your function:
def find_product(dictionary_list, uniqid):
for d in dictionary_list:
if 'uniq_id' in d:
if d['uniq_id'] == uniqid:
return d.keys(), d.values()
return "not found" # or something better
>>> find_product(new_products, '1234')
(dict_keys(['uniq_id', 'sku', 'name', 'list_price', 'sale_price', 'category']), dict_values(['1234', 'abcdefgh', 'Levis skinny jeans', '75.00', '55.00', 'womens']))
>>> find_product(new_products, '12345')
'not found'

Split JSON python string to pass to function

How could I try and split my JSON with all the movies and send them separately to the finalScore function and then append to my list at the end?
Sorry the explain and code was big, I was really unsure of describing and showing my problem without showing what I have done it.
This is my current code:
import datetime, json
def jsonData(data):
return json.loads(data)
def findContentInformation(content):
contentData = convert_content_data(content)
for info in contentData:
contentBaseScore = info['popularityScore']
contentBrand = info['brand']
contentType = info['contentType']
contentName = info['title']
contentInformation = [contentBaseScore, contentBrand, contentType, contentName]
return contentInformation
#Calculator the overall rating for the film
def getRating(content_data, userBrandRate, userTypeRate):
contentScore = {}
#RATING
rating = 0
# Collecting information from the content to be tested
contentInfo = findContentInformation(content_data) # The content being tested
popularityScore += contentInfo[0] #Find base score and add this to popScore
#getBrandRating = str((userBrandPreference[contentInfo[1]])) # Get brand preference
# Check if brand preference rating is a valid rating type
if brandRating in Ratings:
popularityScore += Ratings[brandRating] # Get the ratings score & update popScore
else:
print("Unrecognized rating value found in this search")
user_content_type_preference = convert_type_preferences(content_type_preferences)
typeRating = getTypeRating(user_content_type_preference, contentInfo) # Get the type rating
# Check if type rating is a valid rating
if typeRating in Ratings:
popularityScore += Ratings[typeRating] # Update the popScore based on the rating score
else:
print("Unrecognized rating value found in this search")
contentScore[contentInfo[3]] = popularityScore
popularityScore = 0
return contentScore
result = getRating(content_data)
My output with only one movie (not sure how to use all the movies in the JSON)
JSON string:
content_data = """[{ "title": "Spider-Man", "brand": "Marvel",
"Rating": 98, "contentIs": "movie" }]"""
Output:
[{'Spider-Man': 128}]
To me it feels like you're making things unnecessarily complex. For example, you have three functions (convert_content_data, convert_preferences and convert_type_preferences) that all do the same thing - they all take one JSON encoded string and parse it. Turning those three functions into one would still be one too many functions, because I don't think json.loads, as a single side-effect, is a good candidate for an entirely separate function in the first place.
You do quite a bit of conversion also - from a JSON encoded string to a dictionary. You do that multiple times. Why not convert all your JSON once at the start of the program? Doing so will let you work with dictionaries for the rest of your tasks. Once you have a list of dictionaries, you can think of each dictionary as being one "movie-object", since that is what each dictionary represents. The brand- and content type JSON strings can also be converted once at the start of the program (instead of multiple times throughout the entire program).
EDIT - I've updated my example code.
First, I think you should put your movie data in a separate JSON file, so that you're not poluting your source code with a huge string literal. Let's name it movies.json:
[
{
"title": "Spider-Man",
"brand": "Marvel",
"availability": ["CA","FR","US"],
"availableDate": "2019-11-12T05:00:00.000Z",
"isKidsContent": true,
"popularityScore": 98,
"contentType": "movie"
},
{
"title": "Float",
"brand": "Pixar",
"availability": ["US"],
"availableDate": "2019-11-12T05:00:00.000Z",
"isKidsContent": true,
"popularityScore": 87,
"contentType": "short"
},
{
"title": "Avatar",
"brand": "21st Century Fox",
"availability": ["US","CA","FR","ES","DE"],
"availableDate": "2019-11-12T05:00:00.000Z",
"isKidsContent": false,
"popularityScore": 99,
"contentType": "movie"
},
{
"title": "Chapter 1: The Mandalorian",
"brand": "Star Wars", "availability": ["US","CA"],
"availableDate": "2019-11-02T23:00:00.000Z",
"isKidsContent": false,
"popularityScore": 92,
"contentType": "series"
},
{
"title": "Marvel Studios Avengers: Endgame",
"brand": "Marvel",
"availability": ["CA","FR","ES","DE","US"],
"availableDate": "2019-11-11T23:00:00.000Z",
"isKidsContent": false,
"popularityScore": 87,
"contentType": "movie"
},
{
"title": "Disney Mickey Mouse Clubhouse: Mickey Goes Fishing",
"brand": "Disney",
"availability": ["US"],
"availableDate": "2019-09-11T22:00:00.000Z",
"isKidsContent": true,
"popularityScore": 75,
"contentType": "series"
},
{
"title": "Disney High School Musical: The Musical: The Series: Act Two",
"brand": "Disney",
"availability": ["US","FR","ES"],
"availableDate": "2020-01-10T08:00:00.000Z",
"isKidsContent": false,
"popularityScore": 97,
"contentType": "series"
}
]
Then, I would also create a JSON file for all of your users. This is where you would store the user preferences. Let's name it users.json:
[
{
"name": "Bob",
"preferences": {
"brand": {
"Star Wars": "love",
"Disney": "like",
"Marvel": "dislike",
"Pixar": "dislike"
},
"contentType": {
"movie": "like",
"series": "like",
"short": "dislike"
}
}
},
{
"name": "Joe",
"preferences": {
"brand": {
"Star Wars": "dislike",
"Disney": "dislike",
"Marvel": "dislike",
"Pixar": "dislike"
},
"contentType": {
"movie": "like",
"series": "like",
"short": "dislike"
}
}
}
]
This users.json file has two users named Bob and Joe, with different preferences.
Then, the code:
def evaluate_score(user, movie):
"""
Evaluates and returns the score a user would assign to
a given movie based on the user's brand- and content-type preferences.
"""
ratings = {
"dislike": -20,
"indifferent": 0,
"like": 10,
"adore": 30,
"love": 50
}
brand_score = ratings.get(user["preferences"]["brand"].get(movie["brand"])) or 0
content_type_score = ratings.get(user["preferences"]["contentType"].get(movie["contentType"])) or 0
return movie["popularityScore"] + brand_score + content_type_score
def get_all_scores(user, movies):
for movie in movies:
yield {
"title": movie["title"],
"score": evaluate_score(user, movie)
}
def main():
import json
from operator import itemgetter
with open("movies.json", "r") as file:
movies = json.load(file)
with open("users.json", "r") as file:
users = json.load(file)
for user in users:
print(user["name"].center(16, "-"))
for movie in sorted(get_all_scores(user, movies), key=itemgetter("score"), reverse=True):
print("{}: {}".format(movie["title"], movie["score"]))
print()
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
Output:
------Bob-------
Chapter 1: The Mandalorian: 152
Disney High School Musical: The Musical: The Series: Act Two: 117
Avatar: 109
Disney Mickey Mouse Clubhouse: Mickey Goes Fishing: 95
Spider-Man: 88
Marvel Studios Avengers: Endgame: 77
Float: 47
------Joe-------
Avatar: 109
Spider-Man: 88
Disney High School Musical: The Musical: The Series: Act Two: 87
Chapter 1: The Mandalorian: 82
Marvel Studios Avengers: Endgame: 77
Disney Mickey Mouse Clubhouse: Mickey Goes Fishing: 65
Float: 47
>>>
We've got two functions and one generator:
evaluate_score (which I called get_movie_score before) takes a user dictionary and a movie dictionary, and returns the score (an integer) which this user would assign to the given movie, based on that user's preferences.
get_all_scores is a generator that takes a user and a list of movie dictionaries. It gets the scores for all movies, according to that user, and yields dictionaries - where each dictionary contains two key-value pairs: The movie title, and the final score assigned by that user. This generator will be userful later in the main function, when we want to print the final result in descending order.
main is the main entry-point of the entire script. It first opens and parses our two JSON files, and then, for every user, print a sorted summary (in descending order based on score) of that user's scores for all movies.

How to show more variables in modules

Im just starting to learn practice it however my problem I bet is easy to resolve I’m trying my best but my knowledge is too low to solve this out , I’ve try commas brackets but still didn’t work I just want to get print the name country and age , sorry for newbie question please help 👍🏼💪🤠
Main.py
import one
a = one.person1["name"]
b = one.person2["name"]
c = one.person3["name"]
def input():
print(one(name))
One.py
person1 = {
"name": "John",
"age": "6",
"country": "Norway"
}
person2 = {
"name": "Jn",
"age": "36",
"country": "Norway"
}
person3 = {
"name": "krun",
"age": "36",
"country": "Norway"
}
If you want to display one person then use every key separatelly
print( one.person1["name"], one.person1["age"], one.person1["country"] )
And then you can format output
print('name =', one.person1["name"])
print('age =', one.person1["age"])
print('country =', one.person1["country"])
You can also display directly print(one.person1) but then you can't format output.
If you want to display all persons then keep them on list and then you can use for-loop
persons = [one.person1, one.person2, one.person2]
for item in persons:
print( item["name"], item["age"], item["country"] )
If you don't know keys then you can use .keys() or .items() in dictionary
for item in persons:
for key, value in item.items():
print(key, '=', value)
if you want to get key from user then
key = input("what to show: ")
print(one.person1[key])
print(one.person2[key])
print(one.person3[key])
or better keep persons on list and use for-loop
key = input("what to show: ")
persons = [one.person1, one.person2, one.person2]
for item in persons:
print( item[key] )

Python: String replacement with JSON dictionary

I need to create a script in Python, for replacement of strings in a json file, based on a json dictionary. The file has information about patents and it looks like this:
{
"US-8163793-B2": {
"publication_date": "20120424",
"priority_date": "20090420",
"family_id": "42261969",
"country_code": "US",
"ipc_code": "C07D417/14",
"cpc_code": "C07D471/04",
"assignee_name": "Hoffman-La Roche Inc.",
"title": "Proline derivatives",
"abstract": "The invention relates to a compound of formula (I) wherein A, R 1 -R 6 are as defined in the description and in the claims. The compound of formula (I) can be used as a medicament."
}
}
Initially I used a software that identifies, based on entities (ex. COMPANY), all the words that are written differently, but are the same. For example, the company "BMW" can be called "BMW Ag" as well as "BMW Group". And this dictionary has a structure like this (is only partially represented, otherwise it would be very long):
{
"RESP_META" : {
,"RESP_WARNINGS" : null
,"RESP_PAYLOAD":
{
"BIOCHEM": [
{
"hitID": "D011392",
"name": "L-Proline",
"frag_vector_array": [
"16#{!Proline!} derivatives"
],
...,
"sectionMeta": {
"8": "$.US-8163793-B2.title|"
}
},
{
(next hit...)
},
...
]
}
Taking into consideration that the "sectionMeta" key gives me the patent ID and, for ex., abstract, title or assignee_name, I would like to use this information to find out in which patent will the replacement take place, and then based on the "frag_vector_array" key, find the word to be replaced, which always is between {!!}, for example {! Proline!}, and that word should be replaced by "name", for ex. L-Proline.
I've tried something to replace the companies name, but I think I'm going the wrong way. Here is the code I started:
import json
patents = json.load(open("testset_patents.json"))
companies = json.load(open("termite_output.json"))
print(companies)
companies = companies['RESP_PAYLOAD']
# loop through companies data
for company in companies.values():
company_list = company["COMPANY"]
for comp in company_list:
comp_name = comp["name"]
# update patents "name" in "assignee_name"
for patent in patents.values():
patent['assignee_name'] = comp_name
print(patents)
# save output in new file
with open('company_replacement.json', 'w') as fp:
json.dump(patents, fp)
Well any and all help is welcome.

Categories