Словарь со списком кортежей в качестве значений. Как заменить кортеж в списке новым кортежем с помощью функции

Используя функцию add_course, я хочу заменить кортеж в списке новым кортежем, если одно из значений в новом кортеже больше соответствующего значения кортежа, который в данный момент находится в списке.

вот мой код:

def add_student(students, name):
    if name not in students:
        # students.update(name:[])
        students[name] = []

def print_student(students, name):
    if name not in students:
        print(f"{name}: no such person in the database")
    elif len(students[name]) < 1:
        print(f"{name}:")
        print(" no completed courses")
        # 
    elif len(students[name]) > 0:
        print(f"{name}:")
        print(f" {len(students[name])} completed courses:")
        for course in students[name]:
            # print(f"{len(students[name])}  completed courses:")
            print(f"  {course[0]} {course[1]}")
        av_grade = 0
        for course in students[name]:
            av_grade += course[1]
        print(f" average grade {av_grade / len(students[name])}")

def add_course(students,name,course: tuple):
    if course[1] == 0:
        return 0
    elif course[0] in students[name]:
        temp = course
        if temp[1] < course[1]:
            return 0
        else:
            course = temp
    students[name].append(course)

if __name__ == "__main__":
    students = {}
    add_student(students, "Peter")
    add_course(students, "Peter", ("Introduction to Programming", 3))
    add_course(students, "Peter", ("Advanced Course in Programming", 2))
    add_course(students, "Peter", ("Data Structures and Algorithms", 0))
    add_course(students, "Peter", ("Introduction to Programming", 2))
    print_student(students, "Peter")

В приведенном выше «основном» коде вы можете видеть, что «Питер» дважды прошел курс «Введение в программирование», и его балл указан как часть кортежа. Если балл Питера выше, чем в первый раз, когда он проходил курс, мне нужно заменить кортеж с более низким баллом на более высокий. И наоборот, если балл Питера меньше, чем в первый раз, когда он проходил курс, мне нужно «не добавлять» пройденный курс («вернуть 0» — моя мысль). Я знаю, что синтаксис моей функции add_course неверен, но надеюсь, что я на правильном пути?

вывод должен быть:

Peter:
 2 completed courses:
  Introduction to Programming 3
  Advanced Course in Programming 2
 average grade 2.5

мой текущий результат:

Peter:
 3 completed courses:
  Introduction to Programming 3
  Introduction to Programming 2
  Advanced Course in Programming 2
 average grade 2.33

Я часами искал решение, но на данный момент я недостаточно разбираюсь в Python, чтобы не обращаться за помощью.

Здравствуйте и добро пожаловать в Stack Overflow! Я думаю, Бармар нашел ответ на этот вопрос. Единственное, что я хотел бы добавить, это то, что по мере того, как вы глубже знакомитесь с Python, обратите внимание на классы для хранения данных и управления ими. Как только вы пройдете один или два уровня вложенности кортежей, списков и словарей, может оказаться очень полезно создать более конкретные и явные абстракции.

CrazyChucky 22.06.2024 18:52

Добро пожаловать в Stack Overflow! Это сайт для конкретных вопросов, поэтому вопрос «я на правильном пути» слишком широк. Я не вижу простого способа перейти к более конкретному вопросу, поскольку с вашей функцией add_course существует множество несвязанных проблем. Я имею в виду, что if temp[1] < course[1] — это хорошо, но почти все остальное там неправильно, включая определение temp.

wjandrea 22.06.2024 18:57

Пожалуйста, прочитайте Как задавать вопросы по домашнему заданию и отвечать на них. Даже если это не домашнее задание как таковое, некоторые из тех же советов все равно применимы, например «Сначала добросовестно попытайтесь решить проблему самостоятельно» и «Спросите о конкретных проблемах с существующей реализацией».

wjandrea 22.06.2024 18:57

Вы можете попытаться разобрать проблему сверху: во-первых, как перебрать список (students[name])? Попробуйте для начала просто распечатать элементы, а затем, как только они у вас будут, переходите к следующему шагу: сравнению названий курсов. См. также Почему вопрос «Может ли кто-нибудь мне помочь?» не полезный вопрос?

wjandrea 22.06.2024 18:59

Кстати, если в списке не может быть повторяющихся курсов, использование dict будет иметь больше смысла.

wjandrea 22.06.2024 19:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Просмотрите список в поисках названия курса. Если вы его найдете, замените этот элемент новым кортежем и вернитесь. Если вы его не нашли, добавьте новый кортеж.

def add_course(students,name,course: tuple):
    if name not in students:
        raise ValueError(f"{name}: no such person in the database")
    if course[1] == 0:
        return
    for i, (cname, cvalue) in enumerate(students[name]):
        if cname == course[0]: # course found, replace it if necessary
            if cvalue < course[1]:
                students[name][i] = course
            return

    # course not found, add it
    students[name].append(course)

Я бы очень рекомендовал здесь использовать namedtuple вместо кортежа, потому что это сделает ваш код более читабельным. Я бы также посоветовал вам использовать dict для хранения курсов, так как это сделает такие операции намного проще и быстрее. В моем примере я конвертирую ваш list в dict вручную, просто чтобы показать, насколько это может быть проще.

from collections import namedtuple

Course = namedtuple("Course", ["name", "score"])

def add_course(students: dict[str, list[Course]], name: str, new_course: Course) -> None:
    if name not in students:
        # Add a student or raise an error

    # Here I build a dict, but you can just store your courses as dict by default.
    courses: dict[str, Course] = {course.name: course for course in students[name]}

    if new_course.name not in courses or new_course.score > courses[new_course.name].score:
        courses[new_course.name] = new_course

    students[name] = list(courses.values())

if __name__ == "__main__":
    students = {}
    add_student(students, "Peter")
    add_course(students, "Peter", Course(name = "Introduction to Programming", score=3))
    add_course(students, "Peter", Course(name = "Advanced Course in Programming", score=2))
    add_course(students, "Peter", Course(name = "Introduction to Programming",score=2))

Надеюсь, это поможет!

Другие вопросы по теме