Iterating through dictionary values in python (.keys() in .values()?) - python

In a programming course I am now at dictionaries point in python. So I have this task in which I need to add a "fail" command, which basically is printing out students if a grade is less than 4. I have googled it and searched for similar problems in here, but just couldn't find a similar example. Hope you can help me. Also, I have added the code and in "def fail():" you can see what was my idea. But there is an error code with this - ValueError: too many values to unpack (expected 2). PS, I'm new to python.
students = {('Ozols', 'Jānis'): {'Math': '10', 'ProgVal': '5', 'Sports': '5'},
('Krumiņa', 'Ilze'): {'Math': '7', 'ProgVal': '3', 'Sports': '6'},
('Liepa', 'Peteris'): {'Math': '3', 'ProgVal': '7', 'Sports': '7'},
('Lapsa', 'Maris'): {'Math': '10', 'ProgVal': '10', 'Sports': '3'}}
courses = ['Math', 'ProgVal', 'Sports']
def fail():
for lName, fName in students.keys():
for course, grade in students.values():
if grade < 4:
print(fName, lName)
while True:
print()
command = input("command:> ")
command = command.lower()
if command == 'fail':
fail()
elif command == 'done':
break
print("DONE")

There're a few issues with your code.
Firstly, you should be using an integer (int) or float to store a student's score. You can fix it by changing them to integers:
students = {('Ozols', 'Jānis'): {'Math': 10, 'ProgVal': 5, 'Sports': 5},
('Krumiņa', 'Ilze'): {'Math': 7, 'ProgVal': 3, 'Sports': 6},
('Liepa', 'Peteris'): {'Math': 3, 'ProgVal': 7, 'Sports': 7},
('Lapsa', 'Maris'): {'Math': 10, 'ProgVal': 10, 'Sports': 3}}
Secondly, you should not be using a loop of students.values() within a loop of students.keys() as it will loop through the entire dictionary again - you want to loop through each subject of the values (which are dictionaries of scores) of each student, which is stored in the list called students.
Try this:
students = {('Ozols', 'Jānis'): {'Math': 10, 'ProgVal': 5, 'Sports': 5},
('Krumiņa', 'Ilze'): {'Math': 7, 'ProgVal': 3, 'Sports': 6},
('Liepa', 'Peteris'): {'Math': 3, 'ProgVal': 7, 'Sports': 7},
('Lapsa', 'Maris'): {'Math': 10, 'ProgVal': 10, 'Sports': 3}}
courses = ['Math', 'ProgVal', 'Sports']
for lName, fName in students.keys():
studentRecord = students[(lName, fName)]
for course in studentRecord:
if studentRecord[course] < 4:
print(fName, lName, course)

Try the below
students = {
('Ozols', 'Jānis'): {
'Math': '10',
'ProgVal': '5',
'Sports': '5'
},
('Krumiņa', 'Ilze'): {
'Math': '7',
'ProgVal': '3',
'Sports': '6'
},
('Liepa', 'Peteris'): {
'Math': '3',
'ProgVal': '7',
'Sports': '7'
},
('Lapsa', 'Maris'): {
'Math': '10',
'ProgVal': '10',
'Sports': '3'
}
}
courses = ['Math', 'ProgVal', 'Sports']
def fail():
for k,v in students.items():
for course, grade in v.items():
if int(grade) < 4:
print(f'{k[0]} {k[1]} failed in {course}')
fail()
output
Krumiņa Ilze failed in ProgVal
Liepa Peteris failed in Math
Lapsa Maris failed in Sports

Related

How Connect Lines That Have Mutual Joints

I have a list of lines like this:
Lines = ['1', '2', '3', '4', '5', '6', '7', '8']
each line has two points I and J:
LinesDetail = {
'1': {
'I': '100',
'J': '101'},
'2': {
'I': '101',
'J': '102'},
'3': {
'I': '256',
'J': '257'},
'4': {
'I': '257',
'J': '258'},
'5': {
'I': '258',
'J': '259'},
'6': {
'I': '304',
'J': '305'},
'7': {
'I': '305',
'J': '306'},
'8': {
'I': '102',
'J': '103'}}
As you see in the picture, some of these lines have mutual points
so they are connected to each other and I need to know which lines are connected to each other.
I tried while loop but I don't have the basic idea of how to solve this kind of problems.
and the result would be:
result = [["1","2","8"],["3","4","5"],["6","7"]]
All Lines Are Vertical
This is a graph problem of finding connected components. A possible interpretation is that the outer keys are labels and the inner dictionaries are the edges (and inner dict values are the nodes). If dependency is not an issue, Python has a nice API networkx that deals with graphs. Specifically, one can use the UnionFind data structure to find the disjoint subsets.
from networkx.utils.union_find import UnionFind
# reverse the label-edge mapping to get a mapping from nodes to edge labels
edges = {}
for k, d in LinesDetail.items():
for v in d.values():
edges.setdefault(v, []).append(k)
# construct union-find data structure
c = UnionFind()
for lst in edges.values():
c.union(*lst)
# get the disjoint sets as sorted lists
result = list(map(sorted, c.to_sets()))
result
# [['1', '2', '8'], ['3', '4', '5'], ['6', '7']]
Not the most optimal solution, but putting it out there since I worked on it
LinesDetail = {
'1': {
'I': '100',
'J': '101'},
'2': {
'I': '101',
'J': '102'},
'3': {
'I': '256',
'J': '257'},
'4': {
'I': '257',
'J': '258'},
'5': {
'I': '258',
'J': '259'},
'6': {
'I': '304',
'J': '305'},
'7': {
'I': '305',
'J': '306'},
'8': {
'I': '102',
'J': '103'}}
Lines = ['1', '2', '3', '4', '5', '6', '7', '8']
results = []
for item in Lines:
match_this = LinesDetail[item]['J']
list_form = []
for key, value in LinesDetail.items():
if match_this == value['I']:
results.append([item, key])
needed_list = []
for i in range(0, len(results)-1):
if results[i][1] == results[i+1][0]:
yes_list = results[i][:1] + results[i+1]
needed_list.append(yes_list)
else:
try:
if results[i][1] == results[i+2][0]:
continue
except:
needed_list.append(results[i+1])
print(needed_list)
output:
[['1', '2', '8'], ['3', '4', '5'], ['6', '7']]

How to merge dict of dict in python

Two dictionary is below
d1 = {'1': {'index': '1', 'sc': '4', 'st': '3'}, '2': {'index': '2', 'sc': '5', 'st': '5'}}
d2 = {'1': {'diff': 1}, '2': {'diff': 0}}
Code is below
z = {**d2, **d1} why this is not working
Tried below code also
def Merge(d1, d2):
return(d2.update(d1))
print(Merge(d1, d2))
Expetec out below
{'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1},
'2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
an alternate way using pandas
>>> import pandas as pd
>>> df = pd.DataFrame(d1)
>>> df2 = pd.DataFrame(d2)
>>> merged_dict = pd.concat([df,df2]).to_dict()
output
>>> merged_dict
{'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1}, '2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
generally, ** will capture any keyword arguments we pass to the function into a dictionary which that attributes arguments will reference. For example:
d1={'a':1,'b':2}
d2={'c':3,'d':4}
def merge(**di):
res = {}
for k, v in di.items():
try:
res[k].append(v)
except KeyError:
res[k] = [v]
return res
print(merge(**d1, **d2))
# {'a': [1], 'b': [2], 'c': [3], 'd': [4]}
However, if we pass in two dictionary with same keys:
d1 = {'1': {'index': '1', 'sc': '4', 'st': '3'}, '2': {'index': '2', 'sc': '5', 'st': '5'}}
d2 = {'1': {'diff': 1}, '2': {'diff': 0}}
def merge(**di):
res = {}
for k, v in di.items():
try:
res[k].append(v)
except KeyError:
res[k] = [v]
return res
print(merge(**d1, **d2))
# TypeError: merge() got multiple values for keyword argument '1'
This error is handled by continuing which keep the original one and skip the second dict key. Sorry I don't have a shorthand method for this.
d1 = {'1': {'index': '1', 'sc': '4', 'st': '3'}, '2': {'index': '2', 'sc': '5', 'st': '5'}}
d2 = {'1': {'diff': 1}, '2': {'diff': 0}}
def merge(*args):
res = {}
for di in args:
for k, v in di.items():
try:
res[k].update(v)
except KeyError:
res[k] = v
return res
print(merge(d1, d2))
# {'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1}, '2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
z = {**d2, **d1}
Overwrites everything in d2 with d1 values for keys '1', and '2'. It is tricky to merge dictionaries with the same keys so you don't overwrite key:value pairs within those keys.
The following will get you to the depth needed in both d1 and d2 to update d1 to your expected output:
d1['1']['diff'] = d2['1']['diff']
d1['2']['diff'] = d2['2']['diff']
print ('d1:', d1)
Output:
d1: {'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1}, '2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
>>> for key in d1:
... d1[key].update(d2[key])
>>> d1
{'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1}, '2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
Update:
If you want in another identifier d3.
d3 = d1.copy()
for key in d3:
d3[key].update(d2[key])
print(d3)
Dictionaries are mutable objects. update function just mutates/updates the object and return None. So, you need to create a copy (so you have another object) and change the new object, if you want initial data unaltered.

How to subtract the values inside a dictionary

I have dictionary below
d = {'1': {'index': '1', 'sc': '4', 'st': '3'},
'2': {'index': '2', 'sc': '5', 'st': '5'}}
I need to create a new key diff with subtract sc - st
expected out
d1 = {'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1},
'2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
d2 = {'1':{'diff': 1}, '2': {'diff': 0}}
Pseudo code
from functools import reduce
d1 = {}
d2 = {}
for i,j in m.items():
#print (j)
for a,b in j.items():
#print (b)
d1['diff'] = reduce(lambda x,y: x-y, [int(i) for i in d.values()])
You can try
d1 = {k: {**v, "diff": int(v['sc']) - int(v['st'])} for k, v in d.items()}
d2 = {k: {"diff": int(v['sc']) - int(v['st'])} for k, v in d.items()}
Result
d1 = {'1': {'index': '1', 'sc': '4', 'st': '3', 'diff': 1}, '2': {'index': '2', 'sc': '5', 'st': '5', 'diff': 0}}
d2 = {'1': {'diff': 1}, '2': {'diff': 0}}

Perform algebraic operations with nested dictionaries using "lambda" and "dictionary comprehension"?

The problem of multiplying two "simple" dictionaries with the help of lambda, I decided as follows:
v1={'product1': '100', 'product2': '120'}
v2={'product1': '3', 'product2': '2'}
foo = lambda dct_1, dct_2: {key: int(dct_2[key]) * int(dct_1[key]) for key in dct_2}
foo(v1, v2)
# Out: {'product1': 300, 'product2': 240}
How can I multiply two nested dictionaries in the same way?
V={'id1': [{'product1': '1', 'product2': '2'}],'id2': [{'product1': '3', 'product2': '4'}]}
Z={'id1': [{'благо1': '10', 'благо2': '25'}], 'id2': [{'product1': '20', 'product2': '15'}]}
The answer should be as follows:
Out:={'id1': [{'product1': '10', 'product2': '50'}], 'id2': [{'product1': '60', 'product2': '60'}]}
I'm using Python3.
I will omit the lambda because that comprehension is already quite long, but basically you could use:
{outerkey: [{innerkey: int(V[outerkey][0][innerkey])*int(Z[outerkey][0][innerkey])
for innerkey in V[outerkey][0]}]
for outerkey in V}
Giving me:
{'id1': [{'product1': 10, 'product2': 50}],
'id2': [{'product1': 60, 'product2': 60}]}
Note: I assumed that the dictionaries had the same keys:
V={'id1': [{'product1': '1', 'product2': '2'}],'id2': [{'product1': '3', 'product2': '4'}]}
Z={'id1': [{'product1': '10', 'product2': '25'}], 'id2': [{'product1': '20', 'product2': '15'}]}

How to convert list into a dictionary by python

old_list = [ ['ID0', 'ID1'], ['4', '8'], ['5', '6'] ]
I want convert list to new list
key = ['id', 'frame', 'length']
new_list = [{'id': 'ID0', 'frame': '4', 'length': '5'}, {'id': 'ID1', 'frame': '8', 'length': '6'}]
Here's a one-line approach:
>>> [{'id':x, 'frame':y, 'length':z} for x,y,z in zip(*old_list)]
[{'length': '5', 'frame': '4', 'id': 'ID0'}, {'length': '6', 'frame': '8', 'id': 'ID1'}]
new_list=[]
for x,y,z in zip(old_list[0],old_list[1], old_list[2]):
dict = {'id' : x, 'frame' : y, 'length': z}
new_list.append(dict)

Categories

Resources