Sets
A set is a group of values with no duplicates and no order. Write the items between curly braces, like a dictionary without the : value part. Put the same value in twice and the set keeps one.
1lit = {3, 1, 4, 1, 5}2print(lit)3print(len(lit))4print(type(lit))
{1, 3, 4, 5}
4
<class 'set'>
The set has four items, not five: the second 1 was dropped. The set of lamps lit tonight is a good example. A lamp is either lit or not; lighting it twice does not count twice.
Removing duplicates
set() turns a list (or a string, or a tuple) into a set, which drops every repeat. That is the quickest way to ask "which different values are there?"
1visits = [2, 5, 2, 7, 5, 2]2print(set(visits))3print(len(set(visits)))4ore = ["iron", "coal", "iron", "gold", "coal"]5print(sorted(set(ore)))6print(sorted(set("banana")))
{2, 5, 7}
3
['coal', 'gold', 'iron']
['a', 'b', 'n']
To get a list again, use sorted(...), which gives a sorted list, or list(...). An empty set is written set(): {} on its own is an empty dictionary.
No order, no index
A set does not keep items in the order you wrote them, and the order you see is not something you can rely on. With strings it can even change every time the program runs. That is why the examples here show sets of strings through sorted().
Because there is no order, there is no "item 0" either:
1lit = {3, 1, 4}2print(4 in lit)3print(lit[0])
True
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(lit[0])
TypeError: 'set' object is not subscriptableTip: If you need order or positions, use a list. If you only need "is it there?" and "no duplicates", use a set.
Adding and removing
add puts one item in; adding an item that is already there does nothing. remove takes one out and is a KeyError if it is missing. discard also takes one out, but stays quiet if it is missing.
1lit = {1, 2}2lit.add(3)3lit.add(2)4print(lit)5lit.remove(1)6print(lit)7lit.discard(9)8print(lit)9lit.remove(9)
{1, 2, 3}
{2, 3}
{2, 3}
Traceback (most recent call last):
File "main.py", line 9, in <module>
lit.remove(9)
KeyError: 9update adds every item from a list or another set. clear() empties the set.
Fast in
in works on lists too, but a list has to be checked item by item from the start. A set goes straight to the right place, so in on a set stays fast even with a million items. When a program asks "have I seen this already?" over and over, use a set.
1seen = {"Mill Lane", "Pond Road"}2print("Pond Road" in seen)3print("Hill Street" in seen)4print("Hill Street" not in seen)5seen.add("Hill Street")6print(len(seen))
True False True 3
not in is the opposite of in. It reads like English, and it works on lists, strings and dictionaries too.
Union, intersection, difference
Sets can be combined, like circles in a diagram. Each operation makes a new set and leaves the two originals as they are.
1mon = {1, 2, 3, 4}2tue = {3, 4, 5}3print(mon | tue)4print(mon & tue)5print(mon - tue)6print(tue - mon)7print(mon ^ tue)
{1, 2, 3, 4, 5}
{3, 4}
{1, 2}
{5}
{1, 2, 5}
| Write | Method | Gives | Here |
|---|---|---|---|
a | b | a.union(b) | everything in a or b (or both) | lamps lit on either day |
a & b | a.intersection(b) | only what is in both | lit on both days |
a - b | a.difference(b) | in a but not in b | lit Monday only |
a ^ b | a.symmetric_difference(b) | in one, not both | lit on just one of the days |
What does this print?
1a = {1, 2, 3}2b = {2, 3, 4}3print(len(a | b), len(a & b))
a | b is {1, 2, 3, 4}: 2 and 3 are in both but count once, so four items. a & b is {2, 3}, two items.
The methods do the same as the symbols. One difference: the methods also take a list, so a.union([7, 8]) works while a | [7, 8] is an error.
Subsets
a <= b asks "is every item of a also in b?", which is the same as a.issubset(b). And == is True when two sets have the same items, whatever order you wrote them in.
1needed = {"lamp", "oil"}2bag = {"oil", "map", "lamp"}3print(needed <= bag)4print(needed.issubset({"oil"}))5print({1, 2, 3} == {3, 2, 1})6print(sorted(bag - needed))
True False True ['map']
Methods at a glance
| Write | What it does |
|---|---|
set(x) | a set of the items in x, duplicates dropped |
s.add(x) | adds x |
s.update(x) | adds every item of x |
s.remove(x) | takes out x (KeyError if missing) |
s.discard(x) | takes out x, if it is there |
s.clear() | takes out everything |
x in s | is x in the set? (fast) |
a | b, a & b, a - b, a ^ b | union, intersection, difference, symmetric difference |
a <= b / a.issubset(b) | is every item of a in b? |
Practice
Write the code, then press Check. A hint costs nothing; the answer is there when you need it.
Different visitors
✓Print how many different house numbers are in the list.
4
1visits = [12, 4, 12, 7, 4, 12, 9]2# Your code here
Still dark
✓all_lamps is every lamp in town, lit the ones Wick has lit. Print the lamps that are still dark, as a sorted list.
[1, 3, 4]
1all_lamps = {1, 2, 3, 4, 5, 6}2lit = {2, 5, 6}3# Your code here
Ore in both mines
✓Print, as a sorted list, the kinds of ore found in both mines.
['coal', 'iron']
1north = ["iron", "coal", "gold", "iron"]2south = ["coal", "copper", "iron"]3# Your code here
What you learned
- A set holds values with no duplicates and no order:
{1, 2, 3}. An empty set isset(). set(list)removes duplicates;sorted(set(...))gives them back as a sorted list.- No order means no index:
s[0]is an error. add,update,removeanddiscardchange a set;inon a set is fast.|,&,-and^combine sets;<=checks for a subset.