Chp-10: Sets#

Chapter Objectives

By the end of this chapter, the student should be able to:

  • Explain the purpose and role of sets.

  • Create and initialize sets in different ways.

  • Perform set operations.

  • Apply set methods.

  • Recognize uniqueness and mutability of sets.

  • Use loops to iterate through set elements.

  • Apply sets to solve real-world problems

Sets#

A set is an unordered collection of values.

  • Sets can contain a mixed type of elements.

  • Since there is no order there is no indexing for sets.

  • Curly brackets {} are used to create sets.

    • {} is NOT an empty set. It is an empty dictionary that will be covered in next chapter.

  • Sets are mutable. so they can be modified like lists.

  • A tuple can be an element of a set.

  • A list cannot be an element of a set.

  • You can use the set() function to convert strings, tuples, and lists into a set.

    • Only unique values are stored in sets (no repetition).

    • You will lose the order of the elements when you use the conversion.

mylist = [1,4,7,7,8]
myset = set(mylist)
print(myset)
{8, 1, 4, 7}

In the code above, the order of the elements in the mylist has been lost, and one of the 7s has been removed when the list is converted to a set.

Create Sets#

# empty set
empty_set = set()

print(f'Empty set        : {empty_set}')
print(f'Type of empty_set: {type(empty_set)}')
Empty set        : set()
Type of empty_set: <class 'set'>
# set with mixed values: str, int, bool, float

mixed_set = {'USA', 2, True, 9.123}  

print(type(mixed_set))
<class 'set'>
# sets do not contain duplicates

mixed_set = {'USA', 2, True, 9.123, 'USA', 'USA', 'USA', 'USA'}      

print(mixed_set)   # only one 'USA' will be in the set mixed_set
{True, 2, 9.123, 'USA'}
  • The tuple below contains mixed data types, including strings, integers, booleans, floats, tuples, lists, and sets.

mixed_tuple = ('USA', 2, True, 9.123, (10,20,30), ['NY', 'NJ'], {'a','b'})       
print(type(mixed_tuple))
<class 'tuple'>
  • The list below contains mixed data types, including strings, integers, booleans, floats, tuples, lists, and sets.

mixed_list = ['USA', 2, True, 9.123, (10,20,30), ['NY', 'NJ'], {'a','b'}]       
print(type(mixed_list))
<class 'list'>
# a list can not be an element of a set

mixed_set = {'USA', 2, True, 9.123, (10,20,30), ['a','b']}         # ERROR

set() function#

The built-in set() function converts strings, tuples, and lists to a set, removing any duplicates and retaining only unique elements.

char_set = set('Hello')  # convert string to set

print(f'Type of char_set: {type(char_set)}')
print(f'char_set        : {char_set}')
Type of char_set: <class 'set'>
char_set        : {'l', 'H', 'o', 'e'}
number_tuple = (1,2,3,4,4,4)
char_set = set(number_tuple)  # convert tuple to set

print(f'Type of char_set: {type(char_set)}')
print(f'char_set        : {char_set}')
Type of char_set: <class 'set'>
char_set        : {1, 2, 3, 4}
number_list = [1,2,3,4,4,4]
char_set = set(number_list)  # convert list to  set

print(f'Type of char_set: {type(char_set)}')
print(f'char_set        : {char_set}')
Type of char_set: <class 'set'>
char_set        : {1, 2, 3, 4}

Remark: By using tuple() and list() functions, sets can be converted to tuples and lists, respectively.

  • It’s important to note that the conversion doesn’t preserve any specific order, as sets are inherently unordered collections.

number_set = {1,2,3,4}   # set

number_tuple = tuple(number_set)      # set ---> tuple

print(f'Type of number_tuple: {type(number_tuple)}')
print(f'number_tuple        : {number_tuple}')
Type of number_tuple: <class 'tuple'>
number_tuple        : (1, 2, 3, 4)
number_set = {1,2,3,4}   # set

number_list = list(number_set)      # set ---> list

print(f'Type of number_list: {type(number_list)}')
print(f'number_list        : {number_list}')
Type of number_list: <class 'list'>
number_list        : [1, 2, 3, 4]

Functions on sets#

  • len(), max(), min(), and sum() functions can be applied to sets, similar to other data types like tuples and lists.

numbers = {7,3,1,9,6,4}

print(f'Length : {len(numbers)}')
print(f'Maximum: {max(numbers)}')
print(f'Minimum: {min(numbers)}')
print(f'Sum    : {sum(numbers)}')
Length : 6
Maximum: 9
Minimum: 1
Sum    : 30
letters = {'r', 't', 'n', 'a', 'd'}

print(f'Length : {len(letters)}')
print(f'Maximum: {max(letters)}')    # dictionary order
print(f'Minimum: {min(letters)}')
Length : 5
Maximum: t
Minimum: a

Set Operations#

The available operators for sets in Python include:

  • & (intersection)

  • | (union)

  • - (difference)

  • ^ (symmetric difference)

  • in

  • not in

Intersection#

The & (ampersand) operator returns a new set consisting of the common elements of the two sets.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'Intersection of set1 and set2: {set1&set2}')
Intersection of set1 and set2: {3, 4, 5}
  • The intersection() method of sets can also be used to find the common elements between two sets.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 intersection set2  : {set1.intersection(set2)}')
print(f'set1 (No change on set1): {set1}')
set1 intersection set2  : {3, 4, 5}
set1 (No change on set1): {1, 2, 3, 4, 5}

Union#

The | (pipe) operator returns a new set consisting of the combined elements of the two sets.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'Union of set1 and set2: {set1|set2}')
Union of set1 and set2: {1, 2, 3, 4, 5, 6, 7}
  • The union() method of sets can also be used to combine elements from two sets into a new set.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 union set2         : {set1.union(set2)}')
print(f'set1 (No change on set1): {set1}')             
set1 union set2         : {1, 2, 3, 4, 5, 6, 7}
set1 (No change on set1): {1, 2, 3, 4, 5}

Difference#

The - (dash) operator returns a new set consisting of the elements in the first set but not in the second set.

  • set1 - set2: elements in set1 but not in set2.

  • set2 - set1: elements in set2 but not in set1.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 - set2: {set1-set2}')
print(f'set2 - set1: {set2-set1}')
set1 - set2: {1, 2}
set2 - set1: {6, 7}
  • The difference() method of sets can also be used to obtain a new set consisting of the elements in the first set but not in the second set.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 - set2: {set1.difference(set2)}')
print(f'set2 - set1: {set2.difference(set1)}')
set1 - set2: {1, 2}
set2 - set1: {6, 7}

Symmetric Difference#

The ^ (caret) operator returns a new set consisting of elements in either one of the two sets but not both.

  • set1 ^ set2 and set2 ^ set1 are same.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 ^ set2: {set1^set2}')
print(f'set2 ^ set1: {set2^set1}')
set1 ^ set2: {1, 2, 6, 7}
set2 ^ set1: {1, 2, 6, 7}
  • The symmetric_difference() method of sets can also be used to obtain a new set consisting of the elements in either one of the two sets but not both.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

print(f'set1 ^ set2: {set1.symmetric_difference(set2)}')
print(f'set2 ^ set1: {set2.symmetric_difference(set1)}')
set1 ^ set2: {1, 2, 6, 7}
set2 ^ set1: {1, 2, 6, 7}

in & not in#

in checks if a value is part of a set, while not in verifies if a value is absent from a set.

  • Both operations yield a Boolean result, either True or False.

number_set = {1,2,3,4,5}

print(f' 5 is in number_set    : {5  in number_set}' )
print(f' 5 is not in number_set: {5  not in number_set}' )
 5 is in number_set    : True
 5 is not in number_set: False
number_set = {1,2,3,4,5}

print(f' 9 is in number_set    : {9  in number_set}' )
print(f' 9 is not in number_set: {9  not in number_set}' )
 9 is in number_set    : False
 9 is not in number_set: True

Mutable#

Unlike strings and tuples, and similar to lists, sets are mutable, allowing them to be modified.

  • The set methods enable the addition of new elements and the removal of existing ones.

  • Set elements themselves cannot be changed, but new items can be added or existing ones removed.

Set Methods#

Except for the magic methods (those with underscores), there are 17 methods for sets.

  • We have already covered intersection, union, difference, and symmetric difference above.

  • You can execute help(set) for more details.

# methods of sets
# dir() returns a list

print(dir(set))
['__and__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
# non magic methods by using slicing

print(dir(set)[-17:])
['add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

add()#

It adds a new element to a set.

number_set = {1,2,3,4,5}
print(f'number_set before using add(99): {number_set}')

# add 99
number_set.add(99)   

print(f'number_set after  using add(99): {number_set}')
number_set before using add(99): {1, 2, 3, 4, 5}
number_set after  using add(99): {1, 2, 3, 4, 5, 99}

clear()#

It removes all elements from the set, making it an empty set.

number_set = {1,2,3,4,5}
print(f'number_set before using clear(): {number_set}')

# removes all elements
number_set.clear()   

print(f'number_set after  using clear(): {number_set}')
number_set before using clear(): {1, 2, 3, 4, 5}
number_set after  using clear(): set()

copy()#

It returns a new set with the same elements.

number_set = {1,2,3,4,5}
print(f'number_set before using copy(): {number_set}')

# make a copy
number_set_copy = number_set.copy()   

print(f'number_set after  using copy(): {number_set}')
print(f'number_set_copy               : {number_set_copy}')
number_set before using copy(): {1, 2, 3, 4, 5}
number_set after  using copy(): {1, 2, 3, 4, 5}
number_set_copy               : {1, 2, 3, 4, 5}

isdisjoint()#

It checks if there are no common elements between the two given sets.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

# False: 3,4,5 are common
print(f'set1 and set2 are disjoint: {set1.isdisjoint(set2)}' )
set1 and set2 are disjoint: False
set1 = {1,2,3,4,5}
set2 = {10,20,30}

# True: no common element
print(f'set1 and set2 are disjoint: {set1.isdisjoint(set2)}' )
set1 and set2 are disjoint: True

issubset()#

It checks if the first set is a subset of the second set.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

# False: set1 is not subset of set2
print(f'set1 is subset of set2: {set1.issubset(set2)}' )
set1 is subset of set2: False
set1 = {3,4,5}
set2 = {3,4,5,6,7}

# True: set1 is not subset of set2
print(f'set1 is subset of set2: {set1.issubset(set2)}' )
set1 is subset of set2: True

isuperset()#

It checks if the first set contains the second set.

set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}

# False: set1 idoes not contain set2
print(f'set1 is superset of set2: {set1.issuperset(set2)}' )
set1 is superset of set2: False
set1 = {1,2,3,4,5}
set2 = {3,4,5}

# True: set1 contains set2
print(f'set1 is superset of set2: {set1.issuperset(set2)}' )
set1 is superset of set2: True

pop()#

It removes a randomly selected element from the set.

  • If the set is empty, an error message is raised.

number_set = {1,2,3,4,5}
print(f'number_set before using pop(): {number_set}')

# removes a ranodm element
removed_element = number_set.pop()   

print(f'number_set after  using pop(): {number_set}')
print(f'removed element              : {removed_element}')
number_set before using pop(): {1, 2, 3, 4, 5}
number_set after  using pop(): {2, 3, 4, 5}
removed element              : 1

remove()#

It removes the specified element from the set.

  • If the element does not exist in the set, an error message is raised.

number_set = {1,2,3,4,5}
print(f'number_set before using remove(): {number_set}')

# removes 3
number_set.remove(3)   

print(f'number_set after  using remove(): {number_set}')
number_set before using remove(): {1, 2, 3, 4, 5}
number_set after  using remove(): {1, 2, 4, 5}

update()#

  • It adds elements of the second set to the first one.

set1 = {1,2,3}
set2 = {'a', 'b', 'c', 'd'}
print(f'set1 before update: {set1}')

set1.update(set2)

print(f'set1 after  update: {set1}')
set1 before update: {1, 2, 3}
set1 after  update: {1, 2, 3, 'b', 'c', 'd', 'a'}
  • You can also add elements from a tuple or list using the update() method.

myset = {1,2,3}
mytuple = ('a', 'b', 'c', 'd')
print(f'myset before update: {myset}')

myset.update(mytuple)

print(f'myset after  update: {myset}')
myset before update: {1, 2, 3}
myset after  update: {1, 'b', 2, 3, 'c', 'd', 'a'}
myset = {1,2,3}
mylist = ['a', 'b', 'c', 'd']
print(f'myset before update: {myset}')

myset.update(mylist)

print(f'myset after  update: {myset}')
myset before update: {1, 2, 3}
myset after  update: {1, 'b', 2, 3, 'c', 'd', 'a'}

Iterations and Sets#

We can use a for loop to iterate through values in the set and access each element of the set to perform operations on them.

  • Indexes cannot be used, as in tuples and lists, since there is no ordering and indexing for sets.

  • When you run a for loop through a set, the order of the values of the set might be different.

# print state names in states set
states = {'Arizona','Oklahoma', 'Texas', 'Florida', 'California'}   # states is a set

for state in states:
    print(state)       # not in the same order that you see above
Oklahoma
Texas
California
Florida
Arizona