Sorting multi-dictionary in python - python

I have a datastructure like this:
poll = {
'LINK' : {'MoonRaccoon' : 1, 'TheDirtyTree' : 1},
'ZRX' : {'MoonRaccoon' : 1, 'Dontcallmeskaface' : 1, 'TheDirtyTree' : 1},
'XRP' : {'Dontcallmeskaface' : 1},
'XLM' : {'aeon' : 1, 'Bob' : 1}
}
I want it to ultimately print like this ordered by the number of who have requested each, then ticker symbol alphabetically, then the users also alphabetically
!pollresults
ZRX : Dontcallmeskaface, MoonRaccoon, TheDirtyTree
LINK : MoonRaccoon, TheDirtyTree
XLM : aeon, Bob
XRP: Dontcallmeskaface
Anyone really good at sorting that could help me do this.. I'm really new to python and super rusty at coding in general.
Thanks for any help.

Dictionaries can't really be sorted, but for the purposes of printing, this can be done.
poll = {
'LINK' : {'MoonRaccoon' : 1, 'TheDirtyTree' : 1},
'ZRX' : {'MoonRaccoon' : 1, 'Dontcallmeskaface' : 1, 'TheDirtyTree' : 1},
'XRP' : {'Dontcallmeskaface' : 1},
'XLM' : {'aeon' : 1, 'Bob' : 1}
}
def print_polls(poll):
for ticker in sorted(poll, key=lambda t: sum(poll[t].values()), reverse=True):
print(f"{ticker}: {', '.join(sorted(poll[ticker]))}")
This will give you the output you're looking for

Here you get a oneliner:
print (sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True))
Output:
[('ZRX', {'MoonRaccoon': 1, 'Dontcallmeskaface': 1, 'TheDirtyTree': 1}), ('LINK', {'MoonRaccoon': 1, 'TheDirtyTree': 1}), ('XLM', {'aeon': 1, 'Bob': 1}), ('XRP', {'Dontcallmeskaface': 1})]
To pretty print:
lst = sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True)
for elem in lst:
print (elem[0],":"," ".join(elem[1].keys()))
And because I really like oneliners, everything in one line!
print ("\n".join([" : ".join([elem[0]," ".join(list(elem[1].keys()))]) for elem in sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True)]))
Output:
ZRX : MoonRaccoon Dontcallmeskaface TheDirtyTree
LINK : MoonRaccoon TheDirtyTree
XLM : aeon Bob
XRP : Dontcallmeskaface

count the votes in poll, get d
sort d decreasingly
get poll result in the order of step 2, and handle sorting the name lists
d = [[k, len(v)] for k, v in poll.items()]
d.sort(key=lambda name_vote: (-name_vote[-1],name_vote[0]))
pollresults = [name + ' : ' + ', '.join(sorted(poll[name].keys(), key=str.lower)) for name,vote in d]
result:
>>> pollresults
['ZRX : Dontcallmeskaface, MoonRaccoon, TheDirtyTree', 'LINK : MoonRaccoon, TheDirtyTree', 'XLM : aeon, Bob', 'XRP : Dontcallmeskaface']

Related

Python how to parse a list[dict] in python and convert values from nested dictionaries as keys

Need help in writing clean code , I have a yaml parsed output which looks like this :
yaml_output = [{'name' : 'alex', 'subjects' : {'maths' : ['grade_1', 'grade_2']}},
{'name' : 'rio', 'subjects' : {'maths' : ['grade_3', 'grade_2'], 'science : ['grade_4', 'grade_6']}}]
I want it create a list of dictionaries with subjects as key and name of the students as value in a dictionary where grades are the keys.
desired_output = [{'maths' : {'grade_1' : ['alex'], 'grade_2' : ['alex', 'rio'], 'grade_3' : ['rio']}}, {'science' : {'grade_4' : ['rio'], 'grade_6' : ['rio']}
needs subjects as key and name of the students as value in a dictionary where grades are the keys.
new_dict = []
for dict in yaml_output:
for k,v in dict:
for i,j in dict['subjects']:
if any(i in dict_list for dict_list in new_dict):
dict_list[i].append(v)
You were close. Your for k,v loop is looking at the wrong data. You don't want to look at ALL the keys, you want to unravel the subjects key and reference the "name" specifically.
yaml_output = [{'name' : 'alex', 'subjects' : {'maths' : ['grade_1', 'grade_2']}},
{'name' : 'rio', 'subjects' : {'maths' : ['grade_3', 'grade_2'], 'science': ['grade_4', 'grade_6']}}]
out = dict()
for data in yaml_output:
for k,v in data['subjects'].items():
if k not in out:
out[k] = {}
for g in v:
if g not in out[k]:
out[k][g] = []
out[k][g].append( data['name'] )
print(out)
Output:
{'maths': {'grade_1': ['alex'], 'grade_2': ['alex', 'rio'], 'grade_3': ['rio']}, 'science': {'grade_4': ['rio'], 'grade_6': ['rio']}}

In a python dictionary how can I display the content of the key and value of the dictionary entry?

city = {"New York": 2, "Minnespolis": 2, 'thing ' : 3}
print(city)
for key in city:
print(city)
Below I provide you with two option.
Also this iterable is called a dictionary not a directory, although this can be a typo, I'd like to point that out.
Option1
You can use dict.items()
city = {"New York": 2, "Minnespolis": 2, 'thing ' : 3}
for k,v in city.items():
print(f'key: {k}')
print(f'value: {v}')
Option two use dict[key]
city = {"New York": 2, "Minnespolis": 2, 'thing ' : 3}
for k in city:
print(f'key: {k}')
print(f'value: {city[k]}')
output
key: New York
value: 2
key: Minnespolis
value: 2
key: thing
value: 3
Do you mean to access the value by key?
city = {"New York": 2, "Minnespolis": 2, 'thing ' : 3}
print(city)
for key in city:
print(city[key])

Update keys in nested dictionary with some exception in key strings

So I've a list of students which looks something like this :
students = [ {'name': 'Jack' , 'status' : 'Average' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Math' } , 'height' : '20cm' },
{'name': 'Tom' , 'status' : 'Good' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Science' } , 'height' : '30cm' }
]
So the above list is of size 2. Assume that the size is pretty big, lets say 50 or 60 or more.
I want to return a list students_output & for each student I want to return a dictionary which contains the following values for each student which are fetched from the above list but have slightly modified 'keys'. The end output should be something like this :
students_output = [ {'student_name': 'Jack' , 'student_status' : 'Average' , 'student_subjects' : { 'student_subject1' : 'English' , 'student_subject2' : 'Math' } , 'child_height' : '20cm' },
{'student_name': 'Tom' , 'student_status' : 'Good' , 'student_subjects' : { 'student_subject1' : 'English' , 'student_subject2' : 'Science' } , 'child_height' : '30cm' }
]
I am not able to understand how I can create an effective loop so that the keys in my resultant data structure are maintained as provided in the output and i can fetch the data from the first list.
for example, in students_output, I know
students_output[0]['student_name']=students[0]['name']
But can anyone help me do it iteratively ?
In order to achieve this, you have to concatenate "student_" at the start of each key with some exception as "height" key. You may do it via combination of list comprehension and dict comprehension expression as:
students = [
{'name': 'Jack' , 'status' : 'Average' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Math' } , 'height' : '20cm' },
{'name': 'Tom' , 'status' : 'Good' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Science' } , 'height' : '30cm' }
]
def get_key(key):
return {
'height': 'child_height', # All exception you need in `key`
# apart from concatenating `"student_"`
}.get(key, 'student_' + key)
new_list = [{
get_key(k): ({
get_key(kk):v for kk, vv in v.items()} if isinstance(v, dict) else v) \
for k, v in s.items()
} for s in students]
Value hold by new_list will be:
[{'student_name': 'Jack', 'child_height': '20cm', 'student_status': 'Average', 'student_subjects': {'student_subject1': {'subject1': 'English', 'subject2': 'Math'}, 'student_subject2': {'subject1': 'English', 'subject2': 'Math'}}},
{'student_name': 'Tom', 'child_height': '30cm', 'student_status': 'Good', 'student_subjects': {'student_subject1': {'subject1': 'English', 'subject2': 'Science'}, 'student_subject2': {'subject1': 'English', 'subject2': 'Science'}}}]
Here's a quick-and-dirty function that will do what you need:
In [10]: def rename_keys(students):
...: d = {}
...: for k,v in students.items():
...: if isinstance(v,dict):
...: k = "student_" + k
...: v = rename_keys(v)
...: d[k] = v
...: elif k == 'height':
...: k = "child_height"
...: d[k] = v
...: else:
...: k = "student_" + k
...: d[k] = v
...: return d
...:
...:
In [11]: [rename_keys(d) for d in students]
Out[11]:
[{'child_height': '20cm',
'student_name': 'Jack',
'student_status': 'Average',
'student_subjects': {'student_subject1': 'English',
'student_subject2': 'Math'}},
{'child_height': '30cm',
'student_name': 'Tom',
'student_status': 'Good',
'student_subjects': {'student_subject1': 'English',
'student_subject2': 'Science'}}]
And really, this doesn't have to be recursive, you could substitute the recursive call with a dictionary comprehension:
v = {'student_'+key:value for key,value in v.items()}
You can use the following function inside a list comprehension like this:
def new_dict(d):
res = {}
for key, value in d.iteritems():
student_or_child = 'student' if key != 'height' else 'child'
if type(value) == dict:
res['{}_{}'.format(student_or_child, key)] = new_dict(value)
else:
res['{}_{}'.format(student_or_child, key)] = value
return res
The above function takes a dict as argument, for each key, value in the passed dict, if value is of type dict then the same function is called on value, and the result is added to res dict, else the same value is added.
Now, with a list comprehension, we can do:
[new_dict(d) for d in students]
Output:
>>> [new_dict(d) for d in students]
[{'child_height': '20cm', 'student_name': 'Jack', 'student_status': 'Average', 'student_subjects': {'student_subject1': 'English', 'student_subject2': 'Math'}}, {'child_height': '30cm', 'student_name': 'Tom', 'student_status': 'Good', 'student_subjects': {'student_subject1': 'English', 'student_subject2': 'Science'}}]

How to replace a Value in a Dict from another Dict but based on a key value in the first Dict

For say I have two dictionaries like so:
dict1 = {'project' : 'Administration', 'cost_center' : 'N/A'}
{'project' : 'Non-Work Time', 'cost_center' : 'N/A'}
dict2 = {'project':'Administration', 'cost_center': 'F99'}
{'project':'Non-Work Time', 'cost_center': 'F88'}
I need help finding a way to replace 'N/A' with the value from dict2 cost_center. I think an IF statement would be best like: if it finds "N/A" then replace with the value that is in dict2 if it doesn't find that value keep it "N/A"
Example of desired output:
dict1 = {'project' : 'Administration', 'cost_center' : 'F99'}
{'project' : 'Non-Work Time', 'cost_center' : 'F88'}
Pseudo:
if dict1['cost_center'] == "N/A':
Replace 'cost' if 'project' == exists in dict2
else:
continue
You can use a dict comprehension :
>>> dict1 = {'project' : 'Non-Work Time', 'cost' : 'N/A'}
>>> dict2 = {'Administration': 'F99' , 'Non-Work Time': 'Q99'}
>>> dict1 = {i:dict2[dict1['project']] if i=='cost' and j=='N/A' else j for i,j in dict1.items()}
>>> dict1
{'project': 'Non-Work Time', 'cost': 'Q99'}
But note that your dictionaries must contain the expected keys in otherwise it will raise a KeyError.

returned dictionary value is 'None' python

I have a function in a file which I am calling in a separate script (as shown below). Printing directly from the function works correctly, however when I try to return the value to the script it sends 'None'.
Any help would be appreciated.
Thanks
script:
import modules.functions as f
restype = 'THR'
atomtype = 'CA'
print f.AtomType(restype,atomtype)
function: (this is the part of the function which returns the value)
def AtomType(resName,atomType):
def threonine():
print 'well im here'
atoms = {'N' : 1,
'CA': 6,
'C' : 8,
'O' : 2,
'CB': 6,
'OG1': 1,
'CG2': 4,
}
print atoms[atomType]
return atoms[atomType]
residues = {'ALA' : hydrophobic,
'ARG' : arginine,
'ASN' : asparagine,
'ASP' : aspartate,
'CYS' : cysteine,
'GLN' : glutamine,
'GLU' : glutamate,
'GLY' : hydrophobic,
'HIS' : histidine,
'ILE' : hydrophobic,
'LEU' : hydrophobic,
'LYS' : lysine,
'MET' : methionine,
'PHE' : phenylalanine,
'PRO' : proline,
'SER' : serine,
'THR' : threonine,
'TRP' : tryptophan,
'TYR' : tyrosine,
'VAL' : hydrophobic,
}
residues[resName]()
and the output I get is:
well im here
6
None
edit: added entire function
Here's a guess: AtomType calls threonine, but doesn't return its return value.

Categories

Resources