Step 1 of 7 · Reading · ~4 min
Learn
Dictionaries and Sets
Sets and Operations
You will be able to compare groups of items with set algebra instead of nested loops, de-duplicate with or without keeping the order, and avoid the traps in combining more than two sets.
In Dictionary Fundamentals you saw that dict keys must be hashable. Set members follow the same rule for the same reason: a set is an unordered collection of unique, hashable items, much like a dict that keeps only keys.
Building sets
{} is an empty dict, so an empty set is always set(). Converting a list to a set drops duplicates but also drops the order; dict.fromkeys de-duplicates and keeps first-seen order. The last line is a set comprehension, a comprehension in braces with no colon.
add(x) inserts, discard(x) removes quietly, and remove(x) raises KeyError: 9 if 9 is absent. Tuples work as members, so {(1, 2), (2, 1)} holds two pairs.
A set has no order worth printing, and string hashing is randomised per process: the same set of names can print differently on the next run. Use sorted(s) whenever the output matters.
The algebra
Each operation has an operator form and a method form.
The methods union, intersection, difference and symmetric_difference take any iterable, while the operators need a set on both sides:
Comparisons ask a yes/no question: {1, 2} <= x is True (subset), x <= x is True but x < x is False (a proper subset must be strictly smaller), x >= {1, 2} is the superset test, and {1, 2}.isdisjoint({7}) is True because nothing is shared.
Chaining and the parity trap
Operators chain left to right, so a - b - c removes b, then c. ^ is the surprising one. In ^, an item survives if it is in an odd number of the sets, not if it is in exactly one:
Here 1 and 5 sit in one set, but 3 sits in all three and still appears; 2 and 4 sit in two sets and vanish. A chain of ^ therefore answers "odd count", and an "exactly one" or "exactly two" question needs extra set algebra on top of it.
Why in is fast, and sets of sets
x in some_list compares item after item. x in some_set hashes x and jumps to its slot, so the cost barely grows with size. Build the set once, then test against it many times.
A set cannot hold another set, because sets are mutable and unhashable ({{1, 2}} raises TypeError: unhashable type: 'set'). A frozenset is an immutable set, so it can be a member or a dict key, and {frozenset({1, 2}), frozenset({2, 1})} has length 1.
Common mistakes
- Writing
{}for an empty set..addthen fails withAttributeError: 'dict' object has no attribute 'add'. - Printing a set, or joining it, without
sorted. The names come out in a different order from run to run, so an exact-output check fails intermittently. - Reading
a ^ b ^ cas "exactly one". Anyone on all three lists is still in the result. - Swapping the operands of
-.x - yis{1, 2}andy - xis{5, 6}.
Your exercise
You get three lists of guests and must report five groups of them, each printed sorted. The starter reads the lists and handles printing; fill in the five set expressions. The most likely mistake is counting guests on all three lists as "exactly one" or "exactly two".
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…