I currently have a script that uses a number of lists as lookups which have a structure like so:
people.py
roster = ['Bob','Alice','Trent','Eve','Mallory','Chad','Victor','Grace']
roles.py
ClassA = ['Bob','Alice','Trent','Eve']
ClassB = ['Bob','Mallory','Chad','Victor','Grace']
portraits.py
portrait = {
'bob':'bob.png',
'alice':'alice.png',
'trent':'trent.png',
'eve':'eve.png',
'mallory':'mallory.png',
'chad':'chad.png',
'victor':'victor.png',
'grace':'grace.png'
}
main.py
import people
import roles
import portraits
classes=['ClassA','ClassB']
names = people.roster
for name in names:
n = name.replace("-", "").replace("'", "").replace(".", "").replace(" ", "").lower()
picture = portraits.portrait[n]
for p in classes:
rslt = getattr(roles, p)
#more operations here, e.g. a dataframe filter: df = df[df['name'].isin(rslt)]
I would like to move all of this into a uniform data structure like this as it would be easier to maintain:
persons.json
{
"title":"person-schema",
"revdate":"02-21-2022",
"data":[
{
"name":"Bob",
"uid":"bob",
"id":"s001",
"portrait":"bob.png",
"classes": ["ClassA","ClassB"],
"attributes":[
{
}]
},
{
"name":"Alice",
"uid":"alice",
"id":"s002",
"portrait":"alice.png",
"classes": ["ClassA"],
"attributes":[
{
}]
},
{
"name":"Mallory",
"uid":"mallory",
"id":"s003",
"portrait":"mallory.png",
"classes": ["ClassB"],
"attributes":[
{
}]
}
]
}
I know this is a loaded question, but how would I go about rewriting these lookups?
- people.roster >> ?
- getattr(roles, p) >> ?
- portraits.portrait[n] >>?
CodePudding user response:
I would loop through your roster once, doing the necessary matches foreach. For each name, initiate an empty dict, then fill relevant elements.
Something like...
#initiate empty array to hold data
persons_data = []
for name in name:
person_data = {
"name": name
,"portrait": "{}.png".format(lower(name)) #assumes all persons have photo and standard naming convention
,"classes": []
}
#assumes standard, unique names across both datasets
if name in ClassA:
person_data["classes"].append('ClassA')
if name in ClassB:
person_data["classes"].append('ClassB')
persons_data.append(person_data)
CodePudding user response:
Here's a short helper function to quickly json-ify your data:
from typing import *
from math import log10, floor
import portraits, roles, people
NEXT_ID: Int = 0
def student_to_json(name: str, attrs: List[Dict[Any, Any]] = [{}])-> Dict[str, Any]:
name = name.strip().replace("-", "").replace("'", "").replace(".", "").replace(" ", "").lower()
if name is None or not word.isalpha() or not word.isascii(): return "" # invalid name
NEXT_ID = 1
return {
"name": name.title(),
"uid": name,
"id": f"s{'0' * (3 - floor(log10(NEXT_ID)) 1)}{NEXT_ID - 1}"
"portrait": portraits.portrait.get(name, "blank_avatar.png") # include a default image,
"classes": [c[1] if name.title in c[0] for c in [(roles.ClassA, "ClassA"), (roles.ClassB, "ClassB")]]
"attributes": attrs
}
You could then call this like
import json
import datetime
from datetime import datetime as dt
# import attributes ??
# attributes.data[person_name] = [{"eye-color": "blue", ...}, ...]
with open(f'people-schema.json', 'w ') as fptr:
data = [student_to_json(p, attributes.data.get(p, [{}])) for p in people.roster]
json.dumps({"revdate": dt.now(), "data": data}, fptr) # add attributes as necessary
Everything should then be outputted to a new file called people-schema.json
.
(Added support for students enrolled in more than one class, per @ScottieB's comment)
CodePudding user response:
The persons.json file exists.
I can bring it in using something like:
jsonfile = 'persons.json'
with open(jsonfile) as j:
data = json.load(j)
For clarification of the ask:
Old method for referencing the list:
names = people.roster
New method?
names = [x["name"] for x in data.itervalues()]
?
Reference: Get all values from child elements of a dict as a list