Kodewick
Lesson 12 of 31Contents

Sets

Lesson 12 of 31 · Part 2 · Collections and loops · about 15 minutes

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.

main.py
1lit = {3, 1, 4, 1, 5}2print(lit)3print(len(lit))4print(type(lit))
Output
{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?"

main.py
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")))
Output
{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:

main.py
1lit = {3, 1, 4}2print(4 in lit)3print(lit[0])
Output
True
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(lit[0])
TypeError: 'set' object is not subscriptable

Tip: 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.

main.py
1lit = {1, 2}2lit.add(3)3lit.add(2)4print(lit)5lit.remove(1)6print(lit)7lit.discard(9)8print(lit)9lit.remove(9)
Output
{1, 2, 3}
{2, 3}
{2, 3}
Traceback (most recent call last):
  File "main.py", line 9, in <module>
    lit.remove(9)
KeyError: 9

update 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.

main.py
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))
Output
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.

main.py
1mon = {1, 2, 3, 4}2tue = {3, 4, 5}3print(mon | tue)4print(mon & tue)5print(mon - tue)6print(tue - mon)7print(mon ^ tue)
Output
{1, 2, 3, 4, 5}
{3, 4}
{1, 2}
{5}
{1, 2, 5}
WriteMethodGivesHere
a | ba.union(b)everything in a or b (or both)lamps lit on either day
a & ba.intersection(b)only what is in bothlit on both days
a - ba.difference(b)in a but not in blit Monday only
a ^ ba.symmetric_difference(b)in one, not bothlit on just one of the days
Guess first

What does this print?

1a = {1, 2, 3}2b = {2, 3, 4}3print(len(a | b), len(a & b))

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.

main.py
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))
Output
True
False
True
['map']

Methods at a glance

WriteWhat 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 sis x in the set? (fast)
a | b, a & b, a - b, a ^ bunion, 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.

Exercise 1

Different visitors

Print how many different house numbers are in the list.

It should print
4
exercise1.py
1visits = [12, 4, 12, 7, 4, 12, 9]2# Your code here
Output
Press Run or Ctrl+Enter
Exercise 2

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.

It should print
[1, 3, 4]
exercise2.py
1all_lamps = {1, 2, 3, 4, 5, 6}2lit = {2, 5, 6}3# Your code here
Output
Press Run or Ctrl+Enter
Exercise 3

Ore in both mines

Print, as a sorted list, the kinds of ore found in both mines.

It should print
['coal', 'iron']
exercise3.py
1north = ["iron", "coal", "gold", "iron"]2south = ["coal", "copper", "iron"]3# Your code here
Output
Press Run or Ctrl+Enter

What you learned

  • A set holds values with no duplicates and no order: {1, 2, 3}. An empty set is set().
  • 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, remove and discard change a set; in on a set is fast.
  • |, &, - and ^ combine sets; <= checks for a subset.