Модуль bisect позволяет вставлять элемент в сортированный по возрастанию список, не нарушая сортировки.
В модуле bisect есть два основных метода:
- одноименный bisect(list, item [, lo [, hi]]) возвращает индекс, куда надо вставить item, при этом можно указывать рассматриваемый диапазон;
- insort с такими же параметрами, который непосредственно вставляет указанный item в list.
Методы bisect и insort реализуют правостороннюю вставку: если объекты равны, то определение индекса элемента или его добавления происходят справа от равного. Есть методы bisect_left и insort_left, которые делают это слева.
В книге «Язык программирования Python» (Россум, Дрейк, Откидач и др., 2001) на стр. 251 приводится пример использования метода bisect для оценки значений несортированного списка, «прикладывая» каждый элемент к сортированному списку. Пример немного изменен:
from bisect import bisect
grades = "FEDCBA"
breakpoints = [30, 44, 66, 75, 85] # нижние пределы оценок
def grade(total): # возвращает оценку по баллу
i = bisect(breakpoints, total) # определяем индекс total в breakpoints (в какой диапазон попала оценка)
return grades[i] # место вставки в breakpoints совпадает с индексом оценки в строке
exams = [83, 54, 65, 38, 21, 67, 91, 42]
g_exams = []
for e in exams:
g_exams.append(grade(e))
print(exams)
print(g_exams)
# использование функции map()
g_exams = map(grade, exams)
print(g_exams) # в Python3 не выводит список
for g in g_exams:
print(g, end=' ')
break
for g in g_exams: # здесь уже нет первого элемента, объект g_exams итерируемый
print(g, end=' ')
Результат:
[83, 54, 65, 38, 21, 67, 91, 42]
['B', 'D', 'D', 'E', 'F', 'C', 'A', 'E']
<map object at 0x222a1d0>
B D D E F C A E
Свой пример:
from bisect import bisect
class pupil:
def __init__(self, pname):
self.name = pname
self.grades = {}
self.g_sum = 0
def add_grade(self, exam, grade):
self.grades[exam] = grade
self.sum_grades(grade)
def sum_grades(self,grade): # метод должен быть приватным
self.g_sum += grade
def __str__(self):
return self.name +': '+ str(self.grades) + ', total: ' + str(self.g_sum)
pupils = []
pupils.append(pupil('Tom'))
pupils.append(pupil('Max'))
pupils.append(pupil('Ben'))
pupils[0].add_grade('math', 65)
pupils[1].add_grade('math', 73)
pupils[2].add_grade('math', 19)
pupils[0].add_grade('biology', 96)
pupils[2].add_grade('physics', 39)
for i in pupils:
print(i)
levels = [1, 2, 3, 4]
levels_value = [100, 150, 200]
pupils_levels = []
for p in pupils:
pupils_levels.append(levels[bisect(levels_value, p.g_sum)])
print(pupils_levels)
Tom: {'biology': 96, 'math': 65}, total: 161
Max: {'math': 73}, total: 73
Ben: {'physics': 39, 'math': 19}, total: 58
[3, 1, 1]