0

I am working with a list of dictionaries:

student_list = [{'id': 12341, 'first_name': 'Alice', 'last_name': 'Anderson',
     'assignments': [('assignment_1', 0), ('assignment_2', 2), ('assignment_3', 4)]},

 {'id': 12342, 'first_name': 'Boris', 'last_name': 'Bank',
   'assignments': [('assignment_1', 1), ('assignment_2', 3), ('assignment_3', 0)]},

 {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape',
   'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]},

 {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson',
   'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]},

 {'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders',
   'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}]

I need to write a function that searches for a dictionary by the students name, looks to see if there is matching assignment name and grade. If there is it returns True, if there isn't it returns False and adds it too the list. I am close with what I have, but regardless of if I type a true or false set if parameters it reads false and adds the assignment in as a tuple.

Can you help me find the missing piece of instruction needed in this function?

def add_grade(student, assignment_name, grade):
  for s in student_list:
    if s['first_name'] == student:
        if any(s['assignments']) == (assignment_name, grade):
          print(True)
        else:
          s['assignments'].append((assignment_name, grade))
          print(False)

add_grade('Carl', 'assignment_2', 2)
print(student_list)

EDIT: The first answer helped me get the code working (Thanks!)

Now I've bulked it out and made it sloppier so that instead of an assignment being added twice with two different grades it puts an output that it exists already. What I have made is bulky and messy, and it seems like the fix should be easy but I can't figure it out. Thoughts?

def add_grade2(student, assignment_name, grade):
  for s in student_list:
    if s['first_name'] == student:
        if (assignment_name, grade) in s['assignments']:
          print(True)
        elif (assignment_name, 0) in s['assignments']:
          print('That assignment has a different grade. ')
          break
        elif (assignment_name, 1) in s['assignments']:
          print('That assignment has a different grade. ')
          break
        elif (assignment_name, 2) in s['assignments']:
          print('That assignment has a different grade. ')
          break
        elif (assignment_name, 3) in s['assignments']:
          print('That assignment has a different grade. ')
          break
        elif (assignment_name, 4) in s['assignments']:
          print('That assignment has a different grade. ')
          break
        else:
          s['assignments'].append((assignment_name, grade))
          print(False)


add_grade2('Alice', 'assignment_1', 3)
print(student_list)

2 Answers 2

1

The issue is that, for a single student, "assignments" is a list of tuples and, in the first, case you compare the whole list to a single tuple, and in the second case, you just check if the assignment_name (the first position of a tuple) is in the list.

You can change the assignment existence check to :

if (assignment_name, grade) in s['assignments']:
    print(True)
else:
    s['assignments'].append((assignment_name, grade))
    print(False)

Additionally, to limit the indentation and make things easier to read, you can use next to find the correct student dictionary. Then you'll have:

def add_grade(student, assignment_name, grade):
    s = next(s for s in student_list if s['first_name'] == student)
    if (assignment_name, grade) in s['assignments']:
        print(True)
    else:
        s['assignments'].append((assignment_name, grade))
        print(False)

Edit: Allowing only one grade per assignment (no overwriting):

for i in range(len(s['assignments'])):
    if s['assignments'][i][0] == assignment_name:
        if s['assignments'][i][1] == grade:
            print(True)
        else:
            print('That assignment has a different grade.')
        return
s['assignments'].append((assignment_name, grade))
print(False)

or (simpler logic, but slightly more computation):

if (assignment_name, grade) in s['assignments']:
    print(True)
elif any(a_name == assignment_name for a_name, _ in s['assignments']):
    print('That assignment has a different grade.')
else:
    s['assignments'].append((assignment_name, grade))
    print(False)

With overwriting:

for i in range(len(s['assignments'])):
    if s['assignments'][i][0] == assignment_name:
        s['assignments'][i] = (assignment_name, grade)
        print(True)
        return
s['assignments'].append((assignment_name, grade))
print(False)
Sign up to request clarification or add additional context in comments.

6 Comments

Great! Thanks! dang I was so close with the second one. The only flaw I see is someone could give multiple grades for the same assignment to a student, but that's obviously a flaw in my program, not in what you provided.
what does the underscore do in "a_name == assignment_name for a_name,** _ **in s['assignments']"
@tsb it's just a variable but using _ conveys that it won't be used anywhere
okay @tsb, updated again to match your current question: see the first code block after the big "Edit"
Great thank you Henry. I was hoping it could be something closer to what I have with just one elif statement, but that may not be possible. Is there a way to make that one elif statement search 0-4?
|
0

The result returned from any will be either True or False. That will never compare equal to (assignment_name, grade).

It's unclear if you want to match only the name, or the name and grade. Either way you will need a loop to search through the possibilities.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.