Properly looping over a dictionary / using dictionaries as databases - python

This looks like a CS 101 style homework but it actually isn't. I am trying to learn more python so I took up this personal project to write a small app that keeps my grade-book for me.
I have a class semester which holds a dictionary of section objects.
A section is a class that I am teaching in which ever semester object I am manipulating (I didn't want to call them classes for obvious reasons). I originally had sections as a list not a dictionary, and when I wanted to add a roster of students to that semester I could do this.
for sec in working_semester.sections:
sec.addRosterFromFile(filename)
Now I have changed the sections member of semester to a dictionary so I can look up a specific one to work with, but I am having trouble when I want to loop over all of them to do something like when I first set up a new semester I want to add all the sections, then loop over them and add students to each. If I try the same code to loop over the dictionary it gives me the key, but I was hoping to get the value.
I have also tried to iterate over a dictionary like this, which I got out of an older stack over flow question
for sec in iter(sorted(working_semester.sections.iteritems())):
sec.addRosterFromFile(filename)
But iter(sorted ... returns a tuple (key, value) not the item so the line in side the loop gives me an error that tuple does not have a function called addStudent.
Currently I have this fix in place where I loop through the keys and then use the key to access the value like this:
for key in working_semester.sections:
working_semester.sections[key].addRosterFromFile(filename)
There has to be a way to loop over dictionary values, or is this not desirable? My understanding of dictionaries is that they are like lists but rather than grabbing an element by its position it has a specific key, which makes it easier to grab the one you want no matter what order they are in. Am I missing how dictionaries should be used?

Using iteritems is a good approach, you just need to unpack the key and value:
for key, value in iter(sorted(working_semester.sections.iteritems())):
value.addRosterFromFile(filename)
If you really only need the value, you could use the aptly named itervalues:
for sec in sorted(working_semester.sections.itervalues()):
sec.addRosterFromFile(filename)
(It's not clear from your example whether you really need sorted there. If you don't need to iterate over the sections in sorted order just leave sorted out.)

Related

Unexpected output when looping through subdictionaries in Python

I have a nested dictionary, where I have tickers to identifiy certain assets in my dictionary and then for each of these assets I would like to store characteristics in a subdictionary for the asset, creating them in a simple loop like the below:
ticker = ["a","bb","ccc"]
ticker_dict = dict.fromkeys(ticker, {"Var":[]})
for key in ticker_dict:
ticker_dict[key]["Var"] = len(key)
From the above output I would expect, that for each ticker/asset it saves the "Var" variable as the length of its name, meaning the following:
{"a":{"Var":1},
"bb":{"Var":2},
"ccc":{"Var":3}}
But, in my view rather weirdly, the result is this
{"a":{"Var":3},
"bb":{"Var":3},
"ccc":{"Var":3}}
To provide further context, the real process is that I have four assets, for which I would like to store dataframes in their subdictionaries as this makes it easy for me to access them later in loops etc. Somehow though, the data from the last asset is simply copied over all assets, eventhogh I explicitly loop through different keys.
What's going on?
PS: I'm not sure how to explain the problem without the sample code, so I might have missed a similar entry on this site. If so, any hints to it would be appreciated as well of course.
In your code, {"Var":[]} is only evaluated once, causing there to be only 1 inner dictionary shared by all keys. Instead, you can use a dictionary comprehension:
ticker_dict = {key:{"Var":[]} for key in ticker}
and it will work as expected.

How to calculate the marks for each group and deduce the average score under each group,

UPDATED QUESTION AND CODE!30.01.2021
This question logically came up after this question - How to find a separate attribute among the records and form a separate collection on it?
I need to calculate the average score of each group.
In the code that the user #itprorh66 suggested, I added a formula for calculating the average score(it works) and a conditional search operator for the grade.
Mister #itprorh66
I decided to modify your code a bit to try to solve my problem myself. But so far unsuccessful.
This code block is working
def srtgr(self):
counthrees=0
countfours=0
countfives=0
midl_average=0
gl=dict() #Dictionary for the group
for s in studinfos:
sd=gl.pop(s.numbgroup,dict())
sd[s.surn]=[s.markgeometry,s.markalgebra,s.markinformatika]
gl[s.numbgroup]=sd
for k,v, in gl.items():
s=f'Group: {k}: \n'
for stdn,grds in v.items():
s+=f' {stdn}\t{grds[0]},{grds[1]},{grds[2]} \n'
print(s)
This is the second part in def srtgr. In this code block I trying to calculate the number of grades (3,4 and 5) in each group, and then find the average grade for each group. With the help of a loop, I start traversing the dictionary and with the help of the branch operator I start counting the scores in each group, but that's what I thought when I wrote this code. In reality, nothing starts and does not count
for grds in gl.items():
if grds.markgeometry==3:
counthrees+=1
if grds.markalgebra==3:
counthrees+=1
if grds.markinformatika==3:
counthrees+=1
if grds.markgeometry==4:
countfours+=1
if grds.markalgebra==4:
countfours+=1
if grds.markinformatika==4:
countfours+=1
if grds.markgeometry==5:
countfives+=1
if grds.markalgebra==5:
countfives+=1
if grds.markinformatika==5:
countfives+=1
midl_average = (counthrees+countfours+countfives)/3
for kk,grds1 in gl.items():
grds=f'Group: {kk}: {grds1}\n'
print(grds)
print(*sorted(gl, key = midl_average, reverse = True))
INPUT DATA
My reputation is litlle and I can not add the picture form my computer and I send the link,where my input data, what I add in class and how my object classes collection showing in the console. And the separated of groups
https://ibb.co/zV1B0HC
How to make it so that the average grade is displayed at the bottom after the list of students in each group?
Or just calculate the average score in each group and enter it into another dictionary?
I figured out the sorting of values ​​in the dictionary.
I tried to make a 2nd dictionary and put the groups there, and then calculate it in a separate assessment unit - it didn't work.
Then I read that in Python you can add a dictionary to a dictionary.
As a result, I tried to add the existing dictionary to the new one, but did not understand how to proceed.
Because grades must be calculated anyway
You cannot use any helper classes, work with only one class.
dict.items() returns key value pairs in a dictionary. Based on the code the v dictionary has two kinds of data
key is a student number and value is a list of grades.
key is a student numbgroup and the value is a list with an empty list in it.
My best guess is you don't want the second type of thing in that dictionary. I can't tell what the redball stuff is supposed to do but currently you make it an empty list, put it in a dictionary that is carrying a totally different kind of info and then overwrite the variable with a float without ever messing with the earlier empty list.
As an aside, don't be afraid of making verbose variable names. It's harder to follow the code when we need to work out what k and v are. That we includes you by the way, even with your own code bad naming can make it harder to diagnose errors.

Dynamic dictionary creation with only value update

So I am new to python and I'm trying to do a small project which I want to do in pure pythonic way not using any additional libraries, where my data set looks like this:
LOC,DATE,ATTRIBUTE,COUNT
A,03/01/19,alpha,6483
A,03/01/19,beta,19
B,03/01/19,gamma,346158
B,02/01/19,gamma,156891
A,02/01/19,delta,1319
A,02/01/19,gamma,15272
A,02/01/19,gamma,56810
I have to transform this data set to this output:
B,02/01/19,gamma, 346158
A,02/01/19,alpha,6483
A,02/01/19,beta,19
B,02/01/19,gamma, 172163
A,02/01/19,delta,1319
B,01/01/19,gamma,56810
The data needs to be sorted by Date, Value, Measure, Loc
I thought that nested dictionaries should work, because I only have to update value of attirbute, LOC can be come the outer key
dict = {A:{}, B:{}}
Then date can be used as the key for the nested dictionary:
dict = {A:{03/01/19:{}, 02/01/19:{}}, B:{03/01/19:{}, 02/01/19:{}}
And keep going forward until I reach Count, and every time I keep updating count. But the code is getting more complex every time, my question:
Is there any other alternative data structure that I could use?
If with a dictionary is there a way to check nested keys and keep adding only new values for every key!
Any help would be really grateful!

Check an object in a list of values

First, I would like to mention I am to automated testing.
I want to add a test case to Robot Framework which will let me choose from a list (which can change).
I have problem with creating keywords to do this.
Can somebody give me a tips to do this?
I have a list, but the values can change. I need to check values inside the list the list.
There is a value in the list that I would like to change.
Edit: The questions applies the list on web page.
In your test case you'll need to import the library Collections.
To check a value in a list you can use the keyword
list should contain value #{MyList} Value
If you want to set a value in the list to something else you can use the keyword
set list value #{MyList} 1 Value
If you want to learn more about these keywords you can find them here.
http://robotframework.org/robotframework/latest/libraries/Collections.html

Assign many values to an element of a list

If I want to assign to an element of a list only one value I use always a dictionary. For example:
{'Monday':1, 'Tuesday':2,...'Friday':5,..}
But I want to assign to one element of a list many values, like for example:
Monday: Jogging, Swimming, Skating
Tuesday: School, Work, Dinner, Cinema
...
Friday: Doctor
Is any built-in structure or a simple way to make something like this in python?
My idea: I was thinking about something like: a dictionary which as a key holds a day and as a value holds a list, but maybe there is a better solution.
A dictionary whose values are lists is perfectly fine, and in fact very common.
In fact, you might want to consider an extension to that: a collections.defaultdict(list). This will create a new empty list the first time you access any key, so you can write code like this:
d[day].append(activity)
… instead of this:
if not day in d:
d[day] = []
d[day].append(activity)
The down-side of a defaultdict is that you no longer have a way to detect that a key is missing in your lookup code, because it will automatically create a new one. If that matters, use a regular dict together with the setdefault method:
d.setdefault(day, []).append(activity)
You could wrap either of these solutions up in a "MultiDict" class that encapsulates the fact that it's a dictionary of lists, but the dictionary-of-lists idea is such a common idiom that it really isn't necessary to hide it.

Categories