Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
235: The bisect Module for Sorted Insertion
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:
- Create a sorted list called
cutoffscontaining the values[60, 70, 80, 90]. - Create a corresponding list called
gradescontaining['F', 'D', 'C', 'B', 'A']. - Write a function called
get_grade(score)that uses thebisectmodule to find the correct index of the score within thecutoffslist and returns the corresponding grade from thegradeslist. - Test your function with three scores:
55(should return 'F'),75(should return 'D'), and95(should return 'A').
There are no comments for now.