livepython.net
CHAPTER 14Tuples and Sets
14.3  SETS

Python Sets: Unique Items, add(), remove() and in

What Is a Set in Python?

A set is a collection where every item appears only once, written in curly brackets: {"red", "blue"}. A set has no order and no positions.

PYTHONedit me
colors = {"red", "blue", "red", "green", "blue"}
print(len(colors))
print("red" in colors)
print(sorted(colors))
OUTPUT
3
True
['blue', 'green', 'red']

Five colors went in, but the set kept only three: the repeated "red" and "blue" were dropped by themselves.

Think of it like the guest list for a party. Writing Sunny's name twice doesn't bring two Sunnys. And nobody on the list is "guest number 1": it's only about who is on it.

The rules

  • Items go inside curly brackets, separated by commas.
  • A set never holds the same item twice. Duplicates are dropped, with no error.
  • A set has no order, so there are no indexes: no colors[0].
  • len(), in and a for loop all work.
  • An empty set is set(). Empty curly brackets {} make an empty dictionary (chapter 13).

Show a set with sorted()

Python keeps the items of a set in its own order. That order can look random, and it can even be different on another computer. So when you want to show a set, sort it first: sorted() gives back a list in order, the same every time. You'll see sorted() around every set in this chapter.

Avoid: an index

PYTHONedit me
colors = {"red", "blue"}
print(colors[0])
OUTPUT
TypeError: 'set' object is not subscriptable

Don't be scared of the long word! "Subscriptable" means "you can use [] on it". A set has no first item, so [0] means nothing. Ask with in instead: "red" in colors.

Avoid: {} for an empty set

PYTHONedit me
a = {}
b = set()
print(type(a))
print(type(b))
OUTPUT
<class 'dict'>
<class 'set'>

Common beginner doubt: "Curly brackets? Isn't that a dictionary?" Both use them. A dictionary holds key: value pairs, with a colon. A set holds single items, with no colons.

A set keeps each item once and has no order. Show it in order with sorted().

your turnPredict the output

What will this print?

nums = {3, 1, 3, 2, 1} print(len(nums))
Your turn! What will this code show on the screen?
your turnPick the right idea

How do you make an empty set?

Think about it, then pick one.

Add and Remove Set Items: add(), remove(), discard()

Unlike a tuple, a set can change. add() puts one item in, and remove() or discard() takes one out.

PYTHONedit me
guests = {"Sunny", "Rocky"}
guests.add("Lucky")
guests.add("Sunny")
print(len(guests))
guests.remove("Rocky")
print(sorted(guests))
OUTPUT
3
['Lucky', 'Sunny']

Adding "Sunny" a second time did nothing: no error, and no second Sunny.

Think of it like the member list of a club: you can add a member or remove one. Adding someone who's already a member changes nothing.

The three methods

MethodWhat it doesIf the item isn't there
add(x)puts x inadds it (if it's already there, nothing happens)
remove(x)takes x outKeyError
discard(x)takes x outnothing happens

Avoid: remove() on a missing item

PYTHONedit me
guests = {"Sunny"}
guests.remove("Rocky")
OUTPUT
KeyError: 'Rocky'

The error names the item that wasn't there. Use discard() when the item may be missing, or check with in first:

PYTHONedit me
guests = {"Sunny"}
guests.discard("Rocky")
if "Sunny" in guests:
    guests.remove("Sunny")
print(len(guests))
OUTPUT
0

Common mistake: append()

Lists use append(). Sets use add(), because a set has no end to append to:

PYTHONedit me
guests = {"Sunny"}
guests.append("Lucky")
OUTPUT
AttributeError: 'set' object has no attribute 'append'

Building a set in a loop

Start with an empty set() and add() inside a for loop, the way you built lists in chapter 10:

PYTHONedit me
seen = set()
for word in ["hi", "yo", "hi", "hey", "yo"]:
    seen.add(word)
print(len(seen))
print(sorted(seen))
OUTPUT
3
['hey', 'hi', 'yo']

add() puts an item in, remove() takes it out (or errors), discard() takes it out quietly.

your turnSpot the bug

Which line breaks?

One line stops this program. Tap it.
your turnFill the gap

Put mango into the set

fruits = {"apple"} fruits.?("mango") print(len(fruits))

It should print: 2

Which piece makes this code work?

Remove Duplicates from a List with a Set

The most common job for a set: removing duplicates from a list. Turn the list into a set with set(), and every repeat disappears.

PYTHONedit me
votes = ["tea", "coffee", "tea", "juice", "coffee", "tea"]
unique = set(votes)
print(len(votes), "votes")
print(len(unique), "different drinks")
print(sorted(unique))
OUTPUT
6 votes
3 different drinks
['coffee', 'juice', 'tea']

Think of it like a coin album with one slot for each kind of coin. However many copies of a coin you have, the album shows each kind once.

The rules

  • set(my_list) makes a set of the different items. The list itself doesn't change.
  • len(set(my_list)) counts the different items.
  • sorted(set(my_list)) gives a list of the different items, in order.
  • len(set(my_list)) == len(my_list) is True when the list has no duplicates.

Count the different words

Mix it with split() from chapter 12, and you can count the different words in a sentence:

PYTHONedit me
text = "the cat and the dog and the bird"
words = text.split()
print(len(words), "words")
print(len(set(words)), "different words")
OUTPUT
8 words
5 different words

Keep the first order

sorted() puts the items in A to Z order. What if you need them in the order they first appeared? Use a set as a memory inside a for loop: it remembers what you've already seen, and a list keeps the order.

PYTHONedit me
names = ["Rocky", "Sunny", "Rocky", "Lucky", "Sunny"]
seen = set()
result = []
for name in names:
    if name not in seen:
        seen.add(name)
        result.append(name)
print(result)
OUTPUT
['Rocky', 'Sunny', 'Lucky']

Each round asks "have I seen this name?". If not, the name goes into both: the set to remember it, the list to keep it in order.

Common beginner doubt: "Why not check if name not in result?" That works too! But in on a list checks the items one by one, while a set finds an item almost at once. On a list of millions of names, the set is much faster.

set(my_list) drops the duplicates. Use sorted() or a seen set to put the items back in order.

your turnType the output

Type what this prints

nums = [4, 4, 2, 4, 2] print(len(set(nums)))
Read the code line by line, then type the output exactly.
your turnPredict the output

Remember split() from chapter 12?

print("a b a".split())
Your turn! What will this code show on the screen?

Set Operations: Union, Intersection and Difference

Two sets can be compared with three signs: | (union: in either set), & (intersection: in both sets) and - (difference: in the first set but not the second).

PYTHONedit me
sunny = {"chess", "cricket", "music"}
rocky = {"music", "football", "chess"}
print(sorted(sunny | rocky))
print(sorted(sunny & rocky))
print(sorted(sunny - rocky))
print(sorted(rocky - sunny))
OUTPUT
['chess', 'cricket', 'football', 'music']
['chess', 'music']
['cricket']
['football']

Think of it like two friends comparing hobbies: all the hobbies between us (union), the hobbies we share (intersection), and the hobbies only I have (difference).

The three signs

  • a | b, the union: every item that is in a or in b, or in both. Each item still appears once.
  • a & b, the intersection: only the items that are in a and in b.
  • a - b, the difference: the items of a that are not in b. Order matters: a - b and b - a are different.

An easy way to remember: read | as "or" and & as "and", like the or and and from chapter 8.

Each sign makes a new set. The two sets you started with don't change.

A real job: who hasn't handed in?

PYTHONedit me
class_list = {"Sunny", "Rocky", "Lucky"}
handed_in = {"Sunny", "Lucky"}
missing = class_list - handed_in
print("Missing:", sorted(missing))
print("Handed in:", len(class_list & handed_in))
OUTPUT
Missing: ['Rocky']
Handed in: 2

One line finds everyone who is on the class list but not on the handed-in list. With lists, that would take a whole loop.

Avoid: + on sets

Lists and tuples join with +, but sets don't:

PYTHONedit me
a = {1, 2}
b = {3}
print(a + b)
OUTPUT
TypeError: unsupported operand type(s) for +: 'set' and 'set'

Use a | b to put two sets together.

| means in either, & means in both, - means in the first only.

your turnPredict the output

What will this print?

a = {1, 2, 3} b = {2, 3, 4} print(len(a & b))
Your turn! What will this code show on the screen?
your turnFix the code

Fix the code so it prints the names in both teams: ['Lucky', 'Rocky']

It should print: ['Lucky', 'Rocky']

team_a = {"Sunny", "Rocky", "Lucky"}
team_b = {"Rocky", "Lucky"}
print(sorted(team_a + team_b))
This code does not work yet. Fix it, then press Run.

Practice: Sets

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 124.Python Program to Count Unique Words in a SentenceEasySolve
  2. 125.Python Program to Find the First Repeated WordMediumSolve
  3. 126.Python Program to Find Common Friends Using SetsMediumSolve