-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy path03_sets.py
More file actions
299 lines (223 loc) · 9.43 KB
/
03_sets.py
File metadata and controls
299 lines (223 loc) · 9.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
"""
================================================================================
File: 03_sets.py
Topic: Python Sets - Unordered Collections of Unique Elements
================================================================================
This file demonstrates Python sets, which are unordered collections that
store only unique elements. Sets are highly optimized for membership testing
and mathematical set operations.
Key Concepts:
- Creating sets
- Adding and removing elements
- Set operations (union, intersection, difference)
- Frozen sets (immutable sets)
- Use cases for sets
================================================================================
"""
# -----------------------------------------------------------------------------
# 1. Creating Sets
# -----------------------------------------------------------------------------
# Sets are created with curly braces {} or set()
print("--- Creating Sets ---")
# Using curly braces
fruits = {"apple", "banana", "cherry"}
print(f"Fruits set: {fruits}")
# Duplicates are automatically removed
numbers = {1, 2, 2, 3, 3, 3, 4}
print(f"Numbers (duplicates removed): {numbers}")
# Empty set - must use set(), not {}
empty_set = set() # {} creates an empty dictionary!
print(f"Empty set: {empty_set}, type: {type(empty_set)}")
print(f"Empty dict: {{}}, type: {type({})}")
# From other iterables
from_list = set([1, 2, 3, 4, 5])
from_string = set("hello") # Unique characters
from_tuple = set((10, 20, 30))
print(f"\nFrom list: {from_list}")
print(f"From string 'hello': {from_string}")
print(f"From tuple: {from_tuple}")
# -----------------------------------------------------------------------------
# 2. Set Characteristics
# -----------------------------------------------------------------------------
# Unordered, no duplicates, no indexing
print("\n--- Set Characteristics ---")
colors = {"red", "green", "blue"}
# Sets are unordered - no indexing
# colors[0] # This would raise an error!
# Check membership (very fast - O(1))
print(f"'red' in colors: {'red' in colors}")
print(f"'yellow' in colors: {'yellow' in colors}")
# Length
print(f"Number of colors: {len(colors)}")
# Sets can only contain immutable (hashable) elements
valid_set = {1, "hello", (1, 2), 3.14} # OK
# invalid_set = {1, [2, 3]} # Error! Lists are not hashable
# -----------------------------------------------------------------------------
# 3. Adding and Removing Elements
# -----------------------------------------------------------------------------
print("\n--- Adding and Removing Elements ---")
languages = {"Python", "Java"}
print(f"Initial: {languages}")
# add() - Add single element
languages.add("JavaScript")
print(f"After add('JavaScript'): {languages}")
# Adding duplicate has no effect
languages.add("Python")
print(f"After add('Python'): {languages}")
# update() - Add multiple elements
languages.update(["C++", "Rust"])
print(f"After update(['C++', 'Rust']): {languages}")
# remove() - Remove element (raises error if not found)
languages.remove("Java")
print(f"After remove('Java'): {languages}")
# discard() - Remove element (no error if not found)
languages.discard("Go") # No error even though "Go" isn't in set
print(f"After discard('Go'): {languages}")
# pop() - Remove and return an arbitrary element
popped = languages.pop()
print(f"Popped: {popped}, Remaining: {languages}")
# clear() - Remove all elements
temp_set = {1, 2, 3}
temp_set.clear()
print(f"After clear(): {temp_set}")
# -----------------------------------------------------------------------------
# 4. Set Operations - Mathematical Operations
# -----------------------------------------------------------------------------
print("\n--- Set Operations ---")
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
print(f"Set A: {a}")
print(f"Set B: {b}")
# Union - Elements in A or B or both
union = a | b # or a.union(b)
print(f"\nUnion (A | B): {union}")
# Intersection - Elements in both A and B
intersection = a & b # or a.intersection(b)
print(f"Intersection (A & B): {intersection}")
# Difference - Elements in A but not in B
difference = a - b # or a.difference(b)
print(f"Difference (A - B): {difference}")
difference_ba = b - a
print(f"Difference (B - A): {difference_ba}")
# Symmetric Difference - Elements in A or B but not both
sym_diff = a ^ b # or a.symmetric_difference(b)
print(f"Symmetric Difference (A ^ B): {sym_diff}")
# -----------------------------------------------------------------------------
# 5. Set Comparison Operations
# -----------------------------------------------------------------------------
print("\n--- Set Comparisons ---")
numbers = {1, 2, 3, 4, 5}
subset = {2, 3}
same = {1, 2, 3, 4, 5}
different = {6, 7, 8}
print(f"numbers: {numbers}")
print(f"subset: {subset}")
# issubset() - Is subset contained in numbers?
print(f"\nsubset.issubset(numbers): {subset.issubset(numbers)}")
print(f"subset <= numbers: {subset <= numbers}")
# issuperset() - Does numbers contain subset?
print(f"numbers.issuperset(subset): {numbers.issuperset(subset)}")
print(f"numbers >= subset: {numbers >= subset}")
# isdisjoint() - Do they share any elements?
print(f"\nnumbers.isdisjoint(different): {numbers.isdisjoint(different)}")
print(f"numbers.isdisjoint(subset): {numbers.isdisjoint(subset)}")
# Equality
print(f"\nnumbers == same: {numbers == same}")
print(f"numbers == subset: {numbers == subset}")
# -----------------------------------------------------------------------------
# 6. Update Operations (Modify in Place)
# -----------------------------------------------------------------------------
print("\n--- Update Operations ---")
# These modify the set in place instead of creating new ones
x = {1, 2, 3}
y = {3, 4, 5}
# update() - Union in place (|=)
x_copy = x.copy()
x_copy.update(y) # or x_copy |= y
print(f"After update (union): {x_copy}")
# intersection_update() - Intersection in place (&=)
x_copy = x.copy()
x_copy.intersection_update(y) # or x_copy &= y
print(f"After intersection_update: {x_copy}")
# difference_update() - Difference in place (-=)
x_copy = x.copy()
x_copy.difference_update(y) # or x_copy -= y
print(f"After difference_update: {x_copy}")
# symmetric_difference_update() - Symmetric difference in place (^=)
x_copy = x.copy()
x_copy.symmetric_difference_update(y) # or x_copy ^= y
print(f"After symmetric_difference_update: {x_copy}")
# -----------------------------------------------------------------------------
# 7. Frozen Sets (Immutable Sets)
# -----------------------------------------------------------------------------
print("\n--- Frozen Sets ---")
# Frozen sets are immutable versions of sets
frozen = frozenset([1, 2, 3, 4, 5])
print(f"Frozen set: {frozen}")
# Can perform operations but not modify
print(f"3 in frozen: {3 in frozen}")
print(f"len(frozen): {len(frozen)}")
# These would raise errors:
# frozen.add(6)
# frozen.remove(1)
# Frozen sets can be used as dictionary keys or set elements
nested = {frozenset([1, 2]), frozenset([3, 4])}
print(f"Set of frozensets: {nested}")
# -----------------------------------------------------------------------------
# 8. Set Comprehensions
# -----------------------------------------------------------------------------
print("\n--- Set Comprehensions ---")
# Basic set comprehension
squares = {x**2 for x in range(1, 6)}
print(f"Squares: {squares}")
# With condition
even_squares = {x**2 for x in range(1, 11) if x % 2 == 0}
print(f"Even squares: {even_squares}")
# From string - unique vowels
text = "Hello, World!"
vowels = {char.lower() for char in text if char.lower() in "aeiou"}
print(f"Unique vowels in '{text}': {vowels}")
# -----------------------------------------------------------------------------
# 9. Practical Use Cases
# -----------------------------------------------------------------------------
print("\n--- Practical Use Cases ---")
# 1. Remove duplicates from a list
my_list = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_list = list(set(my_list))
print(f"Remove duplicates: {my_list} → {unique_list}")
# 2. Find common elements
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = set(list1) & set(list2)
print(f"Common elements: {common}")
# 3. Find unique elements across lists
all_elements = set(list1) | set(list2)
print(f"All unique elements: {all_elements}")
# 4. Check if all required items exist
required_skills = {"Python", "SQL", "Git"}
candidate_skills = {"Python", "SQL", "Git", "Docker", "AWS"}
has_all_required = required_skills.issubset(candidate_skills)
print(f"\nCandidate has all required skills: {has_all_required}")
# 5. Find missing items
available_items = {"apple", "banana", "orange"}
shopping_list = {"apple", "milk", "bread", "banana"}
need_to_buy = shopping_list - available_items
print(f"Need to buy: {need_to_buy}")
# 6. Count unique words
text = "the quick brown fox jumps over the lazy dog"
unique_words = set(text.split())
print(f"\nUnique words in text: {len(unique_words)}")
print(f"Words: {unique_words}")
# -----------------------------------------------------------------------------
# 10. Performance: Sets vs Lists for Membership Testing
# -----------------------------------------------------------------------------
print("\n--- Performance Note ---")
# Sets use hash tables - O(1) lookup
# Lists use linear search - O(n) lookup
big_list = list(range(10000))
big_set = set(range(10000))
# For membership testing:
# 9999 in big_list # Slow - checks up to 10000 elements
# 9999 in big_set # Fast - direct hash lookup
print("For membership testing, sets are MUCH faster than lists!")
print("Use sets when you frequently check if items exist in a collection.")