Skip to Content
Course content

235: The bisect Module for Sorted Insertion

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you have a physical collection of vinyl records, and you keep them strictly alphabetical on your shelf. When you buy a new record, you don't just throw it at the end of the row and then spend an hour reshuffling every single album to get them back in order. That would be a waste of your time. Instead, you scan the spines, find the exact gap where the new artist fits, and slide the record right in. You've maintained the order without rebuilding the whole system.

In Python, if you have a sorted list and you want to add an element while keeping it sorted, most beginners do something like my_list.append(item) followed by my_list.sort(). I've seen this in countless code reviews. The problem is that sort() is expensive; it's overkill to re-sort a whole list just because one new item arrived. The bisect module is your way of "scanning the spines" and "sliding the record in" efficiently.

Finding the Slot Without the Stress

The bisect module doesn't actually "insert" things by default; its primary job is to tell you where something should go. The bisect_left and bisect_right functions use a binary search algorithm, which is incredibly fast because it repeatedly halves the search area rather than checking every single item from the start.

import bisect

# A sorted list of shipping cost thresholds
thresholds = [10, 20, 50, 100] 

# We want to know where a $35 order fits
index = bisect.bisect_right(thresholds, 35)
print(f"The order fits at index: {index}") 
# Output: The order fits at index: 2

In this case, the index 2 tells us that 35 is greater than 10 and 20, but less than 50. If you're mapping these indices to shipping tiers (e.g., index 0 is "Economy", 1 is "Standard", 2 is "Priority"), you've just found your tier in logarithmic time.

The Subtle Difference Between Left and Right

You'll notice there are two versions: bisect_left and bisect_right. If the item you're inserting isn't already in the list, they do exactly the same thing. But if the item is already there, they behave differently.

  • bisect_left: If the value exists, it gives you the index before the existing entries.
  • bisect_right: If the value exists, it gives you the index after the existing entries.

I usually only care about this distinction when I'm implementing range lookups or dealing with duplicates where the order of arrival matters. For most general purposes, bisect_right is the more intuitive "standard" choice.

Sliding the Record In With Insort

If you don't just want to know the index, but you actually want to put the item into the list, Python provides insort_left and insort_right. These are essentially wrappers that call bisect to find the index and then call list.insert() to put the item there.

import bisect

scores = [72, 85, 91, 99]
new_score = 88

bisect.insort(scores, new_score) 
# 'insort' is an alias for 'insort_right'
print(scores) 
# Output: [72, 85, 88, 91, 99]

Now, a quick word of caution: while insort is much faster than appending and re-sorting, list.insert() itself still has to shift all subsequent elements in memory. If you find yourself doing this thousands of times a second with a massive list, you might want to look into a different data structure entirely, like a heapq or a SortedList from a third-party library. But for the vast majority of scripts, bisect is the elegant, professional way to handle sorted data.




📋 Practical Task

Building a Dynamic Grade Bracket Mapper

You are writing a system for a teacher who doesn't use fixed grade boundaries. Instead, the teacher defines a list of "cutoff" scores, and any student falling between two cutoffs gets a specific grade.

Your Task:

  1. Create a sorted list called cutoffs containing the values [60, 70, 80, 90].
  2. Create a corresponding list called grades containing ['F', 'D', 'C', 'B', 'A'].
  3. Write a function called get_grade(score) that uses the bisect module to find the correct index of the score within the cutoffs list and returns the corresponding grade from the grades list.
  4. Test your function with three scores: 55 (should return 'F'), 75 (should return 'D'), and 95 (should return 'A').
Rating
0 0

There are no comments for now.

to be the first to leave a comment.