#separator:tab
#html:false
#notetype:Basic
#deck:Math::Sets::Sets in Python
#tags:sets python
#columns:Front Back Tags
#tags column:3
How do you write the empty set in Python, and why not {}? set(). The braces {} were taken first by the empty dict, so the empty set has no literal of its own. creating
Predict: set('foo') and {'foo'}. {'f', 'o'} and {'foo'}. set() takes one iterable and adds each item it yields, characters here, with the repeat dropped; braces add each thing written between them, whole. creating
Why does set('a', 'b', 'c') fail? TypeError: set() takes at most one argument, an iterable. Write set(['a', 'b', 'c']) or {'a', 'b', 'c'}. trap
What set is {('a', 'b', 'c')}? A set with ONE member, the tuple ('a', 'b', 'c'). Braces do not unpack what is inside them. trap
Which of these build {'a', 'b', 'c'}: set('abc'), set(['a', 'b', 'c']), set('a', 'b', 'c'), {('a', 'b', 'c')}? The first two. set('a', 'b', 'c') raises TypeError (three arguments); {('a', 'b', 'c')} is a set with one tuple in it. creating
Predict: {2*x for x in [1, 1, 2, 2, 3, 3]}. {2, 4, 6}. A set comprehension applies the rule to every item and drops repeats as it builds. It always draws from a source, which is Zermelo's separation in code. creating
What must be true of every member of a Python set, and why? It must be hashable: hash(x) works and never changes while x is stored. A set is a hash table, and a changed hash would leave the member filed in the wrong slot, lost. hashing
Why does s.add([1, 2, 1]) fail, and what is the fix? TypeError: unhashable type. A list can change, so it cannot be hashed. Add a frozen copy, s.add(tuple([1, 2, 1])), which gives {(1, 2, 1)}. hashing
Is every tuple hashable? No. (1, [2]) is unhashable because it contains a list. The rule is hashable, not immutable: a tuple is only as hashable as its contents. hashing
How many members does {True, 1, 1.0, '1', (1,)} have? 3. True == 1 == 1.0 and they hash alike, so they are one member (the first written, True, is the one kept); '1' and (1,) are two more. hashing
Why does s1.add(s2) fail when s2 is a set, and what did you probably mean? add puts in ONE member, and a set is unhashable, so TypeError. To merge: s1.update(s2) or s1 |= s2. To store s2 as a single member: s1.add(frozenset(s2)). trap
Three ways to get the members of s2 into s1? s1.update(s2) and s1 |= s2 change s1 in place; s1 | s2 builds a new set and leaves both alone. update() accepts any iterable, |= and | need a set on the right. operations
How do you store a whole set as one member of another set? Freeze it first: s1.add(frozenset(s2)). A frozenset cannot change, so it is hashable. frozenset
Is + defined for sets? No: {1} + {2} raises TypeError. + concatenates sequences; the set operation is union, written |. Note that - does work: it is set difference. trap
Give the operator and the method for union, intersection, difference and symmetric difference. | union(), & intersection(), - difference(), ^ symmetric_difference(). Same result on two sets; the methods also accept any iterable. operations
Give the operators for subset, proper subset, superset and proper superset, and the method names. <=, <, >=, >. Methods: issubset() for <= and issuperset() for >=; proper subset and proper superset have no method. operations
Which set test has a method but no operator? isdisjoint(). The nearest operator form is not (a & b), which builds the intersection first. operations
Predict, with a = {1, 2}: a | (3, 4) and a.union((3, 4)). a | (3, 4) raises TypeError (unsupported operand types set and tuple); a.union((3, 4)) returns {1, 2, 3, 4}. Operators need sets on both sides; methods accept any iterable. operators-vs-methods
X = {1, 3, 5}. Does X & [1, 5, 9] work? Does X.intersection([1, 5, 9])? The operator raises TypeError; the method returns {1, 5}. A method converts its argument to a set; an operator does not. operators-vs-methods
a.union(b, c) works. Does a.symmetric_difference(b, c)? No: symmetric_difference takes exactly one argument (TypeError). union, intersection and difference take several. For more sets chain the operator: a ^ b ^ c. operators-vs-methods
Can you call s.__contains__(x) directly? Yes: it is exactly what x in s calls. A note saying it cannot be used is wrong. trap
How is s1 ^ s2 ^ s3 evaluated, and which elements does it keep? Left to right, as (s1 ^ s2) ^ s3. It keeps the elements that are in an ODD number of the three sets, not those in exactly one. chaining
Predict: {0, 1, 2, 3, 4} ^ {2, 3, 4} ^ {2, 5}. {0, 1, 2, 5}. Count occurrences: 0, 1 and 5 once; 2 three times (odd, so it stays); 3 and 4 twice (even, so they cancel). chaining
What are the in-place forms of the set operators? |=, &=, -=, ^= change the left set in place: s |= {11, 22} adds two members. Each needs a set on the right; update() is the iterable-friendly form of |=. operations
How do you test whether two sets are equal? a == b. Only membership counts: {1, 9} == {9, 1} is True, whatever order they were built in. equality
Why is list(a) == list(b) not a test for set equality? Equal sets can iterate in different orders: list({1, 9}) is [1, 9] but list({9, 1}) is [9, 1], so the lists differ while the sets are equal. equality
Why is a.difference(b) == set() not a test for set equality? It only shows a is a subset of b. {1}.difference({1, 2}) is empty, yet {1} != {1, 2}. Use a == b, or check that a ^ b is empty. equality
Predict: set().issubset([]). True. The empty set is a subset of everything, so issubset() of an empty iterable is True for an empty set; it is False only for a non-empty one. trap
What does if (s1 <= s2, s3): actually test? A tuple, (s1 <= s2, s3), which is non-empty and so always true: the branch always runs. Write s1 <= s2 and s1 <= s3. trap
remove(x) versus discard(x) when x is not in the set? remove raises KeyError; discard does nothing. Both remove x when it is present. removing
What does s.pop() do, and what happens on an empty set? Removes and returns an arbitrary member, since a set has no first one. On an empty set it raises KeyError. removing
fs is a frozenset. What does fs.add(3) do, and how do you get a frozenset with 3 added? AttributeError: frozenset has no add. Build a new one, fs.union([3]) or fs | {3}; fs itself is unchanged. frozenset
Predict the types of {1} | frozenset({2}) and frozenset({2}) | {1}. set, then frozenset. When a set and a frozenset are combined, the LEFT operand decides the type of the result. frozenset
How do you remove duplicates from a list and keep first-seen order? list(dict.fromkeys(L)): a dict's keys are a set that remembers insertion order. list(set(L)) may reorder. dedupe
Why does list(set([1, 2, 1, 3])) usually come out sorted, and is that reliable? Luck, not a rule: a small int hashes to itself and lands in slot n mod table size. list(set([10, 3, 8])) is [8, 10, 3], and a set of strings changes order between runs. dedupe
How do you sort a set? sorted(s) returns a sorted list. A set itself has no order and cannot be sorted in place. sorting
How do you sort a set that mixes ints and strings? sorted(s, key=lambda x: (isinstance(x, str), x)). Plain sorted() raises TypeError (int against str); the key puts numbers first, since False < True, and never compares across types. sorting
Why keep a set of visited nodes when walking a graph? A graph with cycles would loop forever without it, and a set answers 'seen already?' with one hash lookup instead of scanning a list. uses
With key sets customers and invoiced, which set operations give the keys of an inner join, an outer join and a left anti-join? customers & invoiced, customers | invoiced, customers - invoiced. A join keeps the rows whose keys survive the set operation. uses
What does B >= A mean for sets, in English and in Polish? B is a superset of A: every member of A is in B. B jest nadzbiorem A. operations
s1 = {'a', 'b', 'c'}, s2 = {'c', 'd', 'e'}. Predict s1 | s2 and s1 & s2. {'a', 'b', 'c', 'd', 'e'} and {'c'}. Union takes every member of either; intersection only the shared 'c'. kata
Predict: set((1, 2, 3)) & set((2, 3, 4)) & set((3, 4, 5)). {3}: the only number in all three. kata
Is set2 < = set1 (with a space) a subset test? No: SyntaxError. <= is a single token; the space splits it into < and =. trap
What does d1.keys() & d2.keys() return? A set of the keys both dicts have. A keys view behaves like a set: |, &, -, ^ and <= all work, and it accepts any iterable on the other side. dict-views
Do dict.items() and dict.values() views support set operations? items() does, when the values are hashable, and it matches only equal key-value pairs. values() does not (TypeError): values can repeat and need not be hashable. dict-views
Predict: s = {1, 2}; s.update({1: 'a', 5: 'e'}); s. {1, 2, 5}. Iterating a dict yields its keys, so update adds 1 and 5 and ignores the values. dict-views
'Remove duplicates' hides two decisions. Which? Which copy represents the group (first seen, last seen, arbitrary), and what order the survivors come in (first-seen, sorted, hash order). Every idiom answers both, silently. dedupe
words = ['Pear', 'fig', 'pear']. Predict list({w.lower(): w for w in words}.values()). ['pear', 'fig']: the LAST spelling at the FIRST spelling's position. A dict keeps a key's first position but overwrites its value on every repeat. dedupe
How do you dedupe by a key and keep the FIRST copy of each group? Loop with d.setdefault(key(x), x): setdefault never overwrites an existing key. Then list(d.values()). dedupe
What does [k for k, _ in groupby(items)] remove? Only ADJACENT repeats: [3, 1, 3] stays [3, 1, 3]. Sort first. It is the same rule as Rust's dedup and ABAP's DELETE ADJACENT DUPLICATES. dedupe
Predict: list(dict.fromkeys([1.0, 1, True])). [1.0]. The three are equal and hash alike, so they are one key, and the first to arrive is kept with its own type. dedupe
How do you remove duplicate rows from a list of lists? Lists are unhashable, so hash a frozen copy: list(dict.fromkeys(map(tuple, rows))). The fallback, if r not in out: out.append(r), works on anything but is quadratic. dedupe
How does ABAP remove duplicates from an internal table? SORT by the fields, then DELETE ADJACENT DUPLICATES COMPARING the same fields (adjacent only; keeps the first of each run). Or INSERT the rows into a table WITH UNIQUE KEY, where the first wins and later duplicates set sy-subrc = 4. dedupe
How does Rust remove duplicates from a Vec? sort() then dedup() gives sorted order and removes adjacent repeats. Filtering with a HashSet, where seen.insert(x) returns true only the first time, keeps first-seen order. dedupe
Why does Python need a second set type, frozenset? A set can change after it is stored, so its hash could change and the container would lose it; Python therefore refuses to hash a set. frozenset drops every mutating method, and so it can be a set member or a dict key. frozenset
Predict: {1, 2} in {frozenset({1, 2})}. True, even though {1, 2} is unhashable: set membership (and remove, discard) treat a set argument as if it were frozen. frozenset
Predict: {frozenset({1, 2}): 'x'}[{1, 2}]. TypeError: unhashable type. A dict lookup does not freeze the key for you; write d[frozenset({1, 2})]. frozenset
t = frozenset({1}); u = t; t |= {2}. What are t and u now? t = frozenset({1, 2}), u = frozenset({1}). A frozenset has no in-place |=, so Python builds a new frozenset and rebinds t; u still names the old one. frozenset
What does f.copy() return for a frozenset f? f itself: f.copy() is f is True. Nothing can change it, so a copy would protect nothing. frozenset
Why does Rust have no frozenset? Immutability belongs to the binding, not the type: let s is frozen, let mut s is not. And the borrow checker never hands out a &mut to a stored member. The exception is interior mutability: BTreeSet| > compiles, and Clippy's mutable_key_type lint warns. frozenset
Can a Rust HashSet contain HashSets? No: HashSet does not implement Hash, because equal sets can iterate in different orders, so insert fails with E0599. Use BTreeSet as the element type; it hashes its members in sorted order. frozenset
How is a set of sets built in ABAP, which has no frozenset? Freeze each inner set into a key by hand, e.g. sort it and join it into a string with a separator, and store that in a HASHED TABLE WITH UNIQUE KEY. frozenset
l1 = ['a', 'a', 'b', 'c', 'd'], l2 = ['a', 'b', 'c', 'f']. Why is set(l1) ^ set(l2) equal to {'d', 'f'} while the Counter version (c1 - c2 | c2 - c1) gives a, d, f? A set drops the copies first, so 'a' is in both and cancels. Counter is a multiset: l1 has two 'a' and l2 one, so one 'a' is left over. Counter has no ^, and - binds tighter than |, so the line is (c1 - c2) | (c2 - c1). dedupe
Predict: bool(set()) and bool({0}). False and True. An empty set is falsy; any non-empty set is truthy, whatever its members. trap
|