#!/usr/bin/python3 # -*- coding: utf-8 -*- """ A set is a mutable collections of unique values, with un-specified ordering of values (there is no 0th, 3rd, or nth element). Items must be hashable, immutable objects, because they are implemented as a hash set (like a hash-table, but key only), a really cool mathemagical data structure! Lookup of items in a set is FAST! No matter the size of the set, it's the same speed! """ from typing import Set, Tuple, List, Union help(set) # %% Sets store mathematical sets. # Make an empty set with the set constructor empty_set = set() # Initialize a set with a bunch of values. # Yeah, it looks a bit like a dictionary... Kind of a dict move python... some_set: Set[int] = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} # Initialize a set from a list how_big: Set[int] = set([1, 1, 1, 1, 2]) print(how_big) # Can add and remove values: x: Set[str] = set() x.add("hey") x.add("there") x.add("hey") print(x) x.remove("hey") print(x) # {} like this makes a heterogeneous set y: Set[Union[int, str]] = {1, "ytn", "aoeu"} print(type(y)) # Similar to keys of a dictionary, elements of a set have to be immutable. # Set with a list and an int (not ok) print("Type: invalid_set = {[1], 1}") # => Raises a TypeError: unhashable type: 'list' # invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' # Set with a tuple and an int (ok) valid_set: Set[Union[Tuple[int], int]] = {(1,), 1} # Sets are mutable (this is a shallow copy below) # Add one more item to the set filled_set: Set[int] = some_set filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} # Sets do not have duplicate elements filled_set.add(5) # it remains as before {1, 2, 3, 4, 5} print(filled_set) other_set: Set[int] = {3, 4, 5, 6} # %% Mathy set operations! # Do set intersection with & print(filled_set & other_set) # => {3, 4, 5} # Do set union with | print(filled_set | other_set) # => {1, 2, 3, 4, 5, 6} # Do set difference with - print({1, 2, 3, 4} - {2, 3, 5}) # => {1, 4} # Do set symmetric difference with ^ print({1, 2, 3, 4} ^ {2, 3, 5}) # => {1, 4, 5} # Check if set on the left is a superset of set on the right print({1, 2} >= {1, 2, 3}) # => False # Check if set on the left is a subset of set on the right print({1, 2} <= {1, 2, 3}) # => True # Check for existence in a set with in print(2 in filled_set) # => True print(10 in filled_set) # => False # Like lists, Sets are mutable, so you need to make a deep copy: # Make a one layer deep copy filled_set = some_set.copy() # filled_set is {1, 2, 3, 4, 5} # Are sets equivalent? print(filled_set is some_set) print(filled_set == some_set) # is checks identity, == checks values # A common use of sets (to count unique values) biglistofrepeatingvalues: List[int] = [1, 2, 3, 2, 3, 4, 5, 7, 7] unique_vals = set(biglistofrepeatingvalues) print(len(unique_vals))