Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python – Grouped Consecutive Range Indices of Elements
Sometimes we need to group consecutive occurrences of elements in a list and track their index ranges. Python provides an efficient approach using defaultdict and groupby from the itertools module to identify consecutive elements and map their start and end indices.
Understanding Grouped Consecutive Range Indices
When elements appear consecutively in a list, we can group them and track their index ranges. For example, in the list [1, 1, 2, 3, 3, 3], element 1 appears at indices 0-1, element 2 at index 2, and element 3 at indices 3-5.
Example with Consecutive Elements
Let's create a list with consecutive duplicate elements to better demonstrate the concept ?
from itertools import groupby
from collections import defaultdict
# List with consecutive duplicate elements
my_list = [10, 10, 20, 30, 30, 30, 40, 40]
print("The list is:")
print(my_list)
my_index = 0
my_result = defaultdict(list)
for key, sub in groupby(my_list):
element_count = len(list(sub))
start_index = my_index
end_index = my_index + element_count - 1
my_result[key].append((start_index, end_index))
my_index += element_count
print("The resultant dictionary is:")
for key, ranges in my_result.items():
print(f"{key}: {ranges}")
The list is: [10, 10, 20, 30, 30, 30, 40, 40] The resultant dictionary is: 10: [(0, 1)] 20: [(2, 2)] 30: [(3, 5)] 40: [(6, 7)]
Example with Non-Consecutive Elements
Here's an example where elements are not consecutive, so each gets its own single-element range ?
from itertools import groupby
from collections import defaultdict
my_list = [63, 12, 84, 91, 52, 39, 25, 27, 20, 11, 0, 9]
print("The list is:")
print(my_list)
my_index = 0
my_result = defaultdict(list)
for key, sub in groupby(my_list):
element_count = len(list(sub))
start_index = my_index
end_index = my_index + element_count - 1
my_result[key].append((start_index, end_index))
my_index += element_count
print("The resultant dictionary is:")
for key, ranges in my_result.items():
print(f"{key}: {ranges}")
The list is: [63, 12, 84, 91, 52, 39, 25, 27, 20, 11, 0, 9] The resultant dictionary is: 63: [(0, 0)] 12: [(1, 1)] 84: [(2, 2)] 91: [(3, 3)] 52: [(4, 4)] 39: [(5, 5)] 25: [(6, 6)] 27: [(7, 7)] 20: [(8, 8)] 11: [(9, 9)] 0: [(10, 10)] 9: [(11, 11)]
How It Works
groupby() groups consecutive identical elements together
defaultdict(list) creates a dictionary with empty lists as default values
For each group, we calculate the start and end indices of consecutive elements
The tuple
(start_index, end_index)represents the range where each element appears consecutively
Multiple Consecutive Groups
Elements can appear in multiple separate consecutive groups ?
from itertools import groupby
from collections import defaultdict
# Element 'A' appears in two separate consecutive groups
my_list = ['A', 'A', 'B', 'C', 'A', 'A', 'A', 'D']
print("The list is:")
print(my_list)
my_index = 0
my_result = defaultdict(list)
for key, sub in groupby(my_list):
element_count = len(list(sub))
start_index = my_index
end_index = my_index + element_count - 1
my_result[key].append((start_index, end_index))
my_index += element_count
print("The resultant dictionary is:")
for key, ranges in my_result.items():
print(f"'{key}': {ranges}")
The list is: ['A', 'A', 'B', 'C', 'A', 'A', 'A', 'D'] The resultant dictionary is: 'A': [(0, 1), (4, 6)] 'B': [(2, 2)] 'C': [(3, 3)] 'D': [(7, 7)]
Conclusion
Using groupby() with defaultdict efficiently groups consecutive elements and tracks their index ranges. This approach is perfect for analyzing sequential patterns in data where you need to know both the element values and their positions.
