Альтернатива вложенным циклам в Python3 - PullRequest
0 голосов
/ 09 февраля 2020

У меня есть фрагмент кода, который сравнивает уровень квалификации студента с уровнем сложности задания. Он пытается сопоставить уровень студента с максимально возможной сложностью задания. Я добился успеха, используя два вложенных цикла for. Тем не менее, это невероятно неэффективно, когда число значений увеличивается.

    def maxAssignmentPoints(self, difficulty, points, student) -> int:
        global totalPoints
        totalPoints = 0
        for i in range(len(student)):
            for j in range(len(difficulty)):
                if student[i] > difficulty[j]:
                    try:
                        if student[i] < difficulty[j + 1]:
                            totalPoints += points[j]
                    except IndexError:
                        break
                if student[i] == difficulty[j]:
                    totalPoints += points[j]
        return str(totalPoints)

Я также изучил использование itertools.product, но я не уверен, как сравнить две переменные в декартовом произведении. results = list(product(student, difficulty)) производит (1,1) (1,2) (1,3) (2,1) ... и так далее. Есть ли способ сравнить значения в паре?

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

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

scores = dict(zip(difficulty, points))

Теперь я чувствую, что он более организован, чем раньше.

def maxAssignmentPoints(self, students, scores) -> int:
    totalPoints = 0
    for student in range(students):
        if scores.get(student, None) is not None:
            total_points += scores[student]
    return str(totalPoints)

Дайте мне знать, если это поможет.

1 голос
/ 09 февраля 2020

Вы пишете: «Однако невероятно неэффективно, когда количество значений увеличивается». Почему? Чем больше данных, тем больше времени требуется для их обработки. Я не думаю, что вложенные циклы являются «невероятной» проблемой для выполнения вашей функции. Производительность может быть увеличена путем использования наиболее подходящих структур данных и их алгоритмов обработки.

Что касается вашей функции, ее можно переписать в более читабельном виде:

def max_assignment_points(difficulties: list, points: list, students: list) -> int:
    total_points = 0
    for student in students:
        for i in range(len(difficulties) - 1):
            if difficulties[i] < student < difficulties[i + 1]:
                total_points += points[i]
            elif student == difficulties[i]:
                total_points += points[i]
    return total_points

PS

Во-первых, это плохая идея - использовать переменную global внутри функции и изменять ее одновременно. Что мешает вам объявить локальную переменную?

Во-вторых, когда вы объявляли функцию, вы писали, что она возвращает значение int, но на самом деле она возвращает str.

В-третьих использование исключения для выхода из oop кажется очень странным.

...