Python Data Structures and Algorithms: Practical Filtering, Sorting, and Tracking Techniques
Filtering Negative Numbers from a List
Using list comprehension provides a clean, readable approach:
from random import randint
numbers = [randint(-10, 10) for _ in range(10)]
positive_only = [n for n in numbers if n >= 0]
print("Original:", numbers)
print("Filtered:", positive_only)
Identifying Stuednts with Scores Above 90
For dictionaries, extract key-value pairs and filter based on values:
from random import randint
grades = {student: randint(60, 100) for student in range(1, 21)}
top_students = [(s, g) for s, g in grades.items() if g > 90]
print("High scorers:", top_students)
Filtering Multiples of Three in a Set
Set comprehensions offer efficiency when filtering unique values:
from random import randint
values = {randint(0, 20) for _ in range(20)}
multiples_of_three = {v for v in values if v % 3 == 0}
print("Multiples of 3:", multiples_of_three)
Improving Readability with Named Tuple Elements
Using collections.namedtuple for Structured Data
Replace positional tuple indexing with named attributes for clarity:
from collections import namedtuple
Student = namedtuple('Student', ['name', 'age', 'gender', 'email'])
student_record = Student('Alice', 20, 'female', 'alice@example.com')
print(f"Name: {student_record.name}")
print(f"Age: {student_record.age}")
print(f"Email: {student_record.email}")
This avoids magic indices like student[0] and enhances code maintainability.
Counting Element Frequencies
Using Counter for Frequency Analysis
The Counter class from collections simplifies frequency counting:
from collections import Counter
from random import randint
data = [randint(0, 15) for _ in range(50)]
freq = Counter(data)
# Top 3 most frequent elements
top_three = freq.most_common(3)
print("Top frequencies:", top_three)
Word Frequency in Text
Apply Counter to tokenize and count words in a docuemnt:
from collections import Counter
import re
with open('sample.txt', 'r') as f:
text = f.read()
words = re.findall(r'\b[a-zA-Z]+\b', text.lower())
word_freq = Counter(words)
top_words = word_freq.most_common(10)
print("Top 10 words:", top_words)
Sorting Dictionary Items by Value
Sort by Value Using Key Parameter
Use sorted() with a lambda to sort dictionary items by value:
from random import randint
scores = {char: randint(60, 100) for char in 'pqrs'}
sorted_by_score = sorted(scores.items(), key=lambda item: item[1])
print("Sorted by score:", sorted_by_score)
Alternative: Using zip for Value-Key Pairs
Pair values with keys and sort directly:
sorted_by_value = sorted(zip(scores.values(), scores.keys()))
print("By value (value, key):", sorted_by_value)
Finding Common Keys Across Multiple Dictionaries
Intersection via Set Operations
Use set intersection to find shared keys efficiently:
from random import randint, sample
dict1 = {k: randint(1, 10) for k in sample('abcdef', randint(3, 5))}
dict2 = {k: randint(1, 10) for k in sample('abcdef', randint(3, 5))}
dict3 = {k: randint(1, 10) for k in sample('abcdef', randint(3, 5))}
common_keys = dict1.keys() & dict2.keys() & dict3.keys()
print("Common keys:", common_keys)
Dynamic Intersection with reduce
For an arbitrary number of dictionaries, use reduce:
from functools import reduce
dictionaries = [dict1, dict2, dict3]
common = reduce(lambda a, b: a & b, (d.keys() for d in dictionaries))
print("Common keys (reduce):", common)
Maintaining Insertion Order in Dictionarise
Using OrderedDict for Ordered Iteration
Though Python 3.7+ preserves insertion order by default, OrderedDict ensures explicit behavior:
from collections import OrderedDict
ordered_map = OrderedDict()
ordered_map['first'] = 100
ordered_map['second'] = 200
ordered_map['third'] = 300
for key, value in ordered_map.items():
print(f"{key}: {value}")
# Output order is guaranteed as inserted
Implementing a Limited History Log with deque
Fixed-Size History Queue
Use deque with a maximum length to automatically discard oldest entries:
from collections import deque
from random import randint
target = randint(1, 100)
history = deque(maxlen=5)
def check_guess(guess):
if guess == target:
print("Correct!")
return True
elif guess < target:
print(f"{guess} is too low")
else:
print(f"{guess} is too high")
return False
while True:
user_input = input("Enter a number (or 'history'): ")
if user_input.isdigit():
guess = int(user_input)
history.append(guess)
if check_guess(guess):
break
elif user_input in ('history', 'h'):
print("Recent guesses:", list(history))
Persisting History with pickle
Save and restore history across sessions:
from collections import deque
import pickle
# Save
history = deque([10, 25, 33, 42, 50], maxlen=5)
with open('history.pkl', 'wb') as f:
pickle.dump(history, f)
# Load
with open('history.pkl', 'rb') as f:
loaded_history = pickle.load(f)
print("Restored history:", list(loaded_history))