DSA Concepts
Quick reference guide for Python Data Structure and Algorithms.
🛠 DSA
List
# 1) Creating lists
empty_list = []
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
# 2) Accessing elements (0-indexed)
print(numbers[0]) # First element: 1
print(numbers[-1]) # Last element: 5
# 3) Slicing [start:end:step]
print(numbers[1:4]) # [2, 3, 4]
print(numbers[::2]) # [1, 3, 5]
print(numbers[::-1]) # [5, 4, 3, 2, 1] (reversed)
# 4) Common operations
numbers.append(6) # Add to end: [1, 2, 3, 4, 5, 6]
numbers.insert(0, 0) # Insert at index: [0, 1, 2, 3, 4, 5, 6]
numbers.pop() # Remove and return last element: 6, list becomes [0, 1, 2, 3, 4, 5]
numbers.pop(0) # Remove at index: 0, list becomes [1, 2, 3, 4, 5]
numbers.remove(3) # Remove by value: [1, 2, 4, 5]
# 5) List methods
nums = [3, 1, 4, 1, 5, 9]
nums.sort() # Sort in-place: [1, 1, 3, 4, 5, 9]
nums.reverse() # Reverse in-place: [9, 5, 4, 3, 1, 1]
print(nums.count(1)) # Count occurrences: 2
print(nums.index(5)) # Find index of value: 1
# 6) List comprehensions
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
even_squares = [x**2 for x in range(10) if x % 2 == 0] # [0, 4, 16, 36, 64]
# 7) Nested lists (matrices)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(matrix[1][2]) # Access element at row 1, col 2: 6
Sets
# 1) Creating sets
empty_set = set() # Empty set (cannot use {} as that creates an empty dict)
fruits = {'apple', 'banana', 'cherry'}
numbers = set([1, 2, 3, 2, 1]) # From iterable - duplicates removed: {1, 2, 3}
# 2) Basic operations
print(len(fruits)) # Number of elements: 3
print('apple' in fruits) # Membership testing: True
# 3) Adding and removing elements
fruits.add('orange') # Add a single element
fruits.update(['mango', 'grapes']) # Add multiple elements
fruits.remove('banana') # Remove element (raises KeyError if not found)
fruits.discard('kiwi') # Remove if present (no error if not found)
popped = fruits.pop() # Remove and return an arbitrary element
fruits.clear() # Remove all elements
# 4) Set operations
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
union = set1 | set2 # Union: {1, 2, 3, 4, 5, 6, 7, 8}
# Alternatively: set1.union(set2)
intersection = set1 & set2 # Intersection: {4, 5}
# Alternatively: set1.intersection(set2)
difference = set1 - set2 # Difference: {1, 2, 3}
# Alternatively: set1.difference(set2)
sym_diff = set1 ^ set2 # Symmetric difference: {1, 2, 3, 6, 7, 8}
# Alternatively: set1.symmetric_difference(set2)
# 5) Subset and superset
set3 = {1, 2}
print(set3.issubset(set1)) # True: set3 ⊆ set1
print(set1.issuperset(set3)) # True: set1 ⊇ set3
print(set1.isdisjoint(set3)) # False: set1 and set3 have elements in common
# 6) Set comprehensions
evens = {x for x in range(10) if x % 2 == 0} # {0, 2, 4, 6, 8}
# 7) Frozen sets (immutable sets)
frozen = frozenset(['a', 'b', 'c'])
# frozen.add('d') # This would raise an AttributeError - cannot modify
Dictionaries
# 1) Creating dictionaries
empty_dict = {}
person = {'name': 'Alice', 'age': 30, 'city': 'New York'}
user = dict(username='john_doe', email='john@example.com') # Alternative creation
# 2) Accessing elements
print(person['name']) # Access by key: 'Alice'
print(person.get('age')) # Safe access: 30
print(person.get('phone', 'Not found')) # With default value: 'Not found'
# 3) Adding and modifying elements
person['phone'] = '555-1234' # Add new key-value pair
person['age'] = 31 # Modify existing value
# 4) Removing elements
del person['city'] # Remove key-value pair
phone = person.pop('phone') # Remove and return value: '555-1234'
last_item = person.popitem() # Remove and return last item as tuple: ('age', 31)
person.clear() # Remove all items
# 5) Dictionary methods
user_info = {'name': 'Bob', 'role': 'admin'}
keys = user_info.keys() # View of keys: dict_keys(['name', 'role'])
values = user_info.values() # View of values: dict_values(['Bob', 'admin'])
items = user_info.items() # View of key-value pairs: dict_items([('name', 'Bob'), ('role', 'admin')])
# These views are dynamic and reflect changes to the dictionary
user_info['department'] = 'IT'
print(list(keys)) # ['name', 'role', 'department']
# 6) Dictionary comprehensions
squares = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 7) Nested dictionaries
employees = {
'alice': {'id': 101, 'dept': 'HR', 'salary': 75000},
'bob': {'id': 102, 'dept': 'IT', 'salary': 80000}
}
print(employees['bob']['salary']) # 80000
# 8) Merging dictionaries
defaults = {'theme': 'light', 'language': 'en'}
user_prefs = {'theme': 'dark'}
# Python 3.9+
merged = defaults | user_prefs # {'theme': 'dark', 'language': 'en'}
# Earlier versions
merged = {**defaults, **user_prefs}
# Or
merged = defaults.copy()
merged.update(user_prefs)
# 9) Default dictionaries (from collections)
from collections import defaultdict
word_count = defaultdict(int) # Default value for missing keys is 0
for word in ['apple', 'banana', 'apple', 'orange']:
word_count[word] += 1
print(dict(word_count)) # {'apple': 2, 'banana': 1, 'orange': 1}
Comprehensions
# Comprehensions are concise ways to create collections in Python
# 1) List comprehensions
numbers = [1, 2, 3, 4, 5]
# Basic syntax: [expression for item in iterable]
squares = [x**2 for x in numbers]
print(squares) # [1, 4, 9, 16, 25]
# With conditional: [expression for item in iterable if condition]
even_squares = [x**2 for x in numbers if x % 2 == 0]
print(even_squares) # [4, 16]
# With if-else in expression: [true_expr if condition else false_expr for item in iterable]
parity = ['even' if x % 2 == 0 else 'odd' for x in numbers]
print(parity) # ['odd', 'even', 'odd', 'even', 'odd']
# 2) Dictionary comprehensions
# Basic syntax: {key_expr: value_expr for item in iterable}
square_dict = {x: x**2 for x in range(1, 6)}
print(square_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# With conditional: {key_expr: value_expr for item in iterable if condition}
even_squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}
print(even_squares) # {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
# Convert between dictionaries
prices = {'apple': 0.40, 'banana': 0.50, 'orange': 0.45}
double_prices = {fruit: price*2 for fruit, price in prices.items()}
print(double_prices) # {'apple': 0.8, 'banana': 1.0, 'orange': 0.9}
# 3) Set comprehensions
# Basic syntax: {expression for item in iterable}
unique_squares = {x**2 for x in [1, 2, 2, 3, 3, 3]}
print(unique_squares) # {1, 4, 9}
# With conditional: {expression for item in iterable if condition}
vowels = {char for char in 'hello world' if char in 'aeiou'}
print(vowels) # {'e', 'o'}
# 4) Generator expressions
# Similar to list comprehensions but use () and create generators (memory efficient)
# Basic syntax: (expression for item in iterable)
square_gen = (x**2 for x in numbers)
print(next(square_gen)) # 1
print(next(square_gen)) # 4
# With conditional: (expression for item in iterable if condition)
even_squares_gen = (x**2 for x in numbers if x % 2 == 0)
print(list(even_squares_gen)) # [4, 16]
# 5) Nested comprehensions
# Creating a flattened list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Creating a matrix (2D list)
grid = [[x + y for x in range(3)] for y in range(3)]
print(grid) # [[0, 1, 2], [1, 2, 3], [2, 3, 4]]
🚌 Built-In Functions
len()
# 1) Length of a string
text = "Hello, world!"
print(len(text))
# 13
# 2) Number of items in a list
fruits = ["apple", "banana", "cherry"]
print(len(fruits))
# 3
# 3) Size of a dictionary
user = {"name": "Alice", "age": 30, "email": "alice@example.com"}
print(len(user))
# 3
# 4) Length of a tuple
coordinates = (10, 20, 30, 40)
print(len(coordinates))
# 4
# 5) Number of items in a set
unique_numbers = {1, 2, 3, 4, 5, 5, 4, 3}
print(len(unique_numbers))
# 5 (duplicates are removed in sets)
max()
# 1) Basic usage with a list
nums = [3, 10, 1]
print(max(nums))
# 10
# 2) With multiple separate arguments
print(max(5, 2, 9, 4))
# 9
# 3) Using key to choose the "largest" by a property (longest string)
words = ["cat", "hippopotamus", "dog"]
print(max(words, key=len))
# hippopotamus
# 4) Max on a list of dicts by a field
students = [
{"name": "Ana", "score": 88},
{"name": "Ben", "score": 92},
{"name": "Chad", "score": 85},
]
top = max(students, key=lambda s: s["score"])
print(top["name"], top["score"])
# Ben 92
min()
# 1) Basic usage with a list
nums = [3, 10, 1, 5]
print(min(nums))
# 1
# 2) With multiple separate arguments
print(min(5, 2, 9, 4))
# 2
# 3) Using key to choose the "smallest" by a property (shortest string)
words = ["cat", "hippopotamus", "dog", "a"]
print(min(words, key=len))
# a
# 4) Min on a list of dicts by a field
students = [
{"name": "Ana", "score": 88},
{"name": "Ben", "score": 92},
{"name": "Chad", "score": 85},
]
lowest = min(students, key=lambda s: s["score"])
print(lowest["name"], lowest["score"])
# Chad 85
abs()
# Returns the absolute value of a number
print(abs(-5))
# 5
print(abs(3.14))
# 3.14
print(abs(-2.718))
# 2.718
# Useful in calculating distances
point1 = (1, 2)
point2 = (4, 6)
distance_x = abs(point2[0] - point1[0])
print(distance_x)
# 3
sum()
# 1) Basic usage with a list of numbers
numbers = [1, 2, 3, 4, 5]
print(sum(numbers))
# 15
# 2) With a start value (adds this to the sum)
print(sum(numbers, 10))
# 25
# 3) Sum with generator expressions
print(sum(x*2 for x in range(5)))
# 20 (0*2 + 1*2 + 2*2 + 3*2 + 4*2)
# 4) Summing floats
floats = [1.5, 2.5, 3.5]
print(sum(floats))
# 7.5
ord()
# Returns the Unicode code point for a character
print(ord('A'))
# 65
print(ord('a'))
# 97
print(ord('🙂'))
# 128578
# Useful for character manipulation and encryption
def simple_cipher(text, shift):
encrypted = ''
for char in text:
if char.isalpha():
# Shift the character by the specified amount
code = ord(char) + shift
encrypted += chr(code)
else:
encrypted += char
return encrypted
print(simple_cipher('abc', 1))
# bcd