## Introduction

A set is an unordered collection of unique elements which are unindexed. Sets are mutable which means they can be modified in-place without creating a new object. However, set items must be of immutable types such as strings, numbers or tuples.

## Defining a Set

A set can be created as a sequence of comma-separated values enclosed within a pair of curly braces {}. The following example demonstrates that sets are unordered, i.e. order of the elements is inconsequential.

Example

Sets are unordered.

1set1 = {23, 85, 41, 19, 22}
2set2 = {41, 22, 85, 23, 19}
3set1 == set2
True

We sometimes say that sets are unindexed. That is, set items cannot be referred to by an index or a key.

Example

Sets are unindexed.

1set1[1] # error: we cannot refer to a set item using an index.
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

~\AppData\Local\Temp/ipykernel_4056/2116443343.py in <module>
----> 1 set1[1] # error: we cannot refer to a set item using an index.

TypeError: 'set' object is not subscriptable

We can get the unique values of a list (or a tuple) by using the set() constructor.

Example

set() constructor.

1list1 = [2, 4, 6, 6, 8, 8, 8, 9]
2set3 = set(list1)
3set3
{2, 4, 6, 8, 9}

We can get the length of a set using the len() function.

Example

Length of a set using len().

1len(set3)
5

Example

Set items must be immutable.

1set4 = {2, 4, 6, "string", (8, 9, 10), 2.4}
2set4
{(8, 9, 10), 2, 2.4, 4, 6, 'string'}

## List vs Tuple vs Dictionary vs Set

Before we proceed, let’s summarize the key properties of the data structures we have learnt so far.

Data Structure Ordered Indexed Mutable Example
List ✔️ ✔️ ✔️ [1,2,3]
Tuple ✔️ ✔️ (1,2,3)
Dictionary ✔️ ✔️ {'a':1 , 'b':2, 'c':3}
Set ✔️ {1,2,3}

As we can see, even though sets are both unindexed and unordered, they are mutable.

## Modifying a Set

Sets are mutable. However, we cannot access or change an element of a set using indexing or slicing since it is unindexed. But we can still add or remove items from a set.

To add one item to a set, we use the add() method.

Example

Adding an item to a set.

1fruits = {'apple', 'orange', 'banana', 'pineapple'}
3fruits
{'apple', 'banana', 'orange', 'pineapple', 'strawberry'}

We use the update() method to add items from one set to another set.

Example

Adding more than one item to a set.

1moreFruits = {"durian", "pear"}
2fruits.update(moreFruits)
3fruits
{'apple', 'banana', 'durian', 'orange', 'pear', 'pineapple', 'strawberry'}

If there are duplicate items in the second set, the update() method will take the union of the items from both sets and update the first set.

Example

update() method will remove duplicates.

1set1 = {1, 2, 3, 4}
2set2 = {2, 4, 6, 8}
3set1.update(set2)
4set1
{1, 2, 3, 4, 6, 8}

We use the remove() method to remove an item from a set.

Example

Remove an item from a set.

1fruits.remove("durian")
2fruits
{'apple', 'banana', 'orange', 'pear', 'pineapple', 'strawberry'}

We can also remove all items from a set using the clear() method.

Example

Remove all items from a set.

1fruits.clear()
2fruits
set()

## Mathematical Set Operations

The union() method is very similar to the update() method. They both produce the same results. There is a subtle difference however. The union method does not modify the original set. Instead, a new set object is created.

Example

union() method.

1set1 = {1, 2, 3, 4}
2set2 = {2, 4, 6, 8}
3print(set1.union(set2))
4print(set1)
{1, 2, 3, 4, 6, 8}
{1, 2, 3, 4}

To store the result, you need to assign a variable to the new object.

1a = set1.union(set2)
2a
{1, 2, 3, 4, 6, 8}

The intersection() method produces the intersection of two sets $A$ and $B$, which is a set of elements that are common to both sets.

Example

intersection() method.

1A = {1, 2, 3, 4, 5}
2B = {4, 5, 6, 7, 8}
3print(A.intersection(B)) # intersection method syntax
4print(A & B) # alternative syntax
{4, 5}
{4, 5}

A slightly different method is the intersection_update() method that produces the same results as the intersection() method but with set $A$ updated.

Example

intersection_update() method.

1A = {1, 2, 3, 4, 5}
2B = {4, 5, 6, 7, 8}
3A.intersection_update(B)
4A
{4, 5}

The difference of two sets $(A - B)$ is the set of all elements of $A$ that are not in $B$. This is accomplished using the difference() method or the alternative syntax A - B.

Example

difference() method.

1A = {1, 2, 3, 4, 5}
2B = {2, 5}
3print(A.difference(B)) # difference method syntax
4print(A - B) #  alternative syntax
{1, 3, 4}
{1, 3, 4}

A slightly different method is the difference_update() method that produces the same results as the difference() method but with set $A$ updated.

Example

difference_update() method.

1A = {1, 2, 3, 4, 5}
2B = {2, 5}
3A.difference_update(B)
4A
{1, 3, 4}

The issubset() method applied to two sets $A$ and $B$ as A.issubset(B) returns True if $A$ is a subset of $B$. That is, all elements of $A$ are present in $B$. Otherwise, it returns False.

Example

issubset() method.

1A = {1, 2, 3, 4, 5}
2B = {2, 5}
3B.issubset(A) # Is B a subset of A?
True

The issuperset() method applied to two sets $A$ and $B$ as A.issuperset(B) returns True if $A$ is a superset of $B$. That is, all elements of $B$ are present in $A$. Otherwise, it returns False.

Example

issuperset() method.

1A = {1, 2, 3, 4, 5}
2B = {2, 5}
3A.issuperset(B) # Is A a superset of B?
True

The isdisjoint() method returns True if 2 sets have no elements in common. Otherwise, it returns False.

Example

isdisjoint() method.

1A = {1, 3}
2B = {2, 5}
3A.isdisjoint(B) # Are A and B disjoint?
True

The following table summarizes all set methods.

Method Description