## ![](https://s3.amazonaws.com/python-ga/images/GA_Cog_Medium_White_RGB.png) {.separator}

Python Programming: Sets and Tuples

--- ## Learning Objectives *After this lesson, you will be able to:* - Perform common actions with sets. - Perform common actions with tuples. - Know when to use different data structures. --- ## Discussion: Lists Here are some lists: ```python unique_colors = ["red", "yellow", "red", "green", "red", "yellow"] subscribed_emails = ["mary@gmail.com", "opal@gmail.com", "mary@gmail.com", "sayed@gmail.com"] ``` What could be a problem here? --- ## Introducing Sets Lists: ```python unique_colors_list = ["red", "yellow", "red", "green", "red", "yellow"] subscribed_emails_list = ["mary@gmail.com", "opal@gmail.com", "mary@gmail.com", "sayed@gmail.com"] ``` Sets: an unordered collection of unique elements. These are powerful because set theory operations can be applied to them in O(1) time. ```python unique_colors_set = {"green", "yellow", "red"} subscribed_emails_set = {"mary@gmail.com", "opal@gmail.com", "sayed@gmail.com"} ``` - Notice the `{}` versus the `[]`. --- ## How Can We Make a Set? If we explicitly cast a set from a list, Python removes duplicates automatically. ```python my_set = set(a_list_to_convert) # In action: unique_colors_list = ["red", "yellow", "red", "green", "red", "yellow"] unique_colors_set = set(unique_colors_list) # => {"green", "yellow", "red"} # In action: unique_colors_set_2 = set(["red", "yellow", "red", "green", "red", "yellow"]) # => {"green", "yellow", "red"} ``` We can make a set directly using curly braces: ```python colors = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"} ``` --- ## Important Note: Sets Lists are always in the same order: - `my_list = ["green", "yellow", "red"]` is always going to be`["green", "yellow", "red"]` - `my_list[0]` is always `"green"`; `my_list[1]` is always `"yellow"`; `my_list[2]` is always `"red"`. Sets are not like this! Similar to dictionaries, they're not ordered. - `my_set = {"green", "yellow", "red"}` could later be `{"red", "yellow", "green"}`! - Note that python defaults to displaying an ascending sort of a set. Although this is displayed to the user when the variable is called via the interpreter, _the order cannot be relied upon_. We **cannot** do: `my_set[0]` - sets are unordered, and a `TypeError` exception will be thrown. --- ## We Do: Creating a Set from a List Let's pull up a new `set_practice.py` file and make some sets! - Make a list `clothing_list` containing the main color of your classmates' clothing. - Using `clothing_list`, make a set named `clothing_set`. - Use a `for` loop to print out both `clothing_list` and `clothing_set`. - Try to print an index! --- ## We Do: Adding to a Set How do we add more to a set? ```python # In a list: clothing_list.append("red") # In a set clothing_set.add("red") ``` `add` vs `append` - this is because we can't guarantee it's going at the end! Let's add a few colors to `clothing_list` and `clothing_set` and then print them. - What happens if you add a duplicate? --- ## We Do: Removing from a List and a Set Remember, lists are always the same order and sets are not! - With the set `{"green", "yellow", "red"}`, `my_set[0]` could be `green`, `red`, or `yellow`. So thus, we need to be careful about removal: ```python # In a list: clothing_list.pop() # Removes and returns the last item in the list. clothing_list.pop(0) # Removes and returns a specific (here, the first) item in the list. # In a set clothing_set.pop() # Removes and returns an arbitrary element. This is probably not what you want to do in most cases. clothing_set.pop(0) # Python throws a TypeError error (pop takes no arguments) clothing_set.remove('red') # This removes an element from the set directly, and raises KeyError if the element is not present. This is the most common use. clothing_set.discard('red') # This removes an element from the set directly, but does NOT throw a KeyError if the element is not present in the set. ``` --- ## We Do: Set Intersection - One thing that sets are _really_ good at is _relational algebra_ (set theory). This is a fancy word for a SQL join, or comparing elements between two sets. - Sets are really good at this because they use the same [hashing trick](https://en.wikipedia.org/wiki/Hash_table) under the hood that dictionaries use and makes them so fast. Let's start by making two sets: ```python set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} ``` --- ## We Do: Set Intersection Now let's use the `.intersection()` set method to find out _what elements these two sets have in common_: ```python set1.intersection(set2) ``` Yields the result: ```python {4, 5} ``` - This makes sense, the two sets share the elements `4` and `5`. - Note that this is commutative, meaning we could also write `set2.intersection(set1)` and receive the same result. --- ## We Do: Set Differences - Instead of finding _elements in common_ between two sets, we can also find _their differences_. - To do this, we use `.difference()`. - Note that this method _is not commutative_, meaning _order matters_. - The difference is what is contained in the _first_ set, _but not in the second set_. ```python set1.difference(set2) ``` Yields the result: ```python {1, 2, 3} ``` ```python set2.difference(set1) ``` Yields the result: ```python {6, 7, 8} ``` --- ## Quick Review: Sets vs. Lists **Lists**: - The original, normal object. - Created with `[]`. - `append()`, `insert(index)`, `pop()`, `pop(index)`. - Duplicates and mutable. **Sets**: - Lists without duplicates. - Created with `{}` or with `set(my_list)`. - `add()` and `remove(element)`. ## Quick Review: Sets vs. Lists ```python ### Creation ### # List my_list = ["red", "yellow", "green", "red"] # Sets my_set = {"red", "yellow", "green"} my_set2 = set(my_list) my_set = set(a_list_to_convert) ### Appending a New Value ### my_list.append("blue") my_set.add("blue") ### Appending a Duplicate ### my_list.append("blue") # => my_list = ["red", "yellow", "green", "red", "blue", "blue"] my_set.add("blue") # => my_set = {"red", "yellow", "green", "blue"} ### Removing items: ### my_list.pop(1) my_set.remove("red") ``` --- ## Discussion: Immutability Thoughts A set is a type of list which doesn't allow duplicates. What if, instead, we have a list we don't want to change? ```python rainbow_colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"] ``` We **don't** want: ```python rainbow_colors[0] = "gray" ## Gray's not in the rainbow! rainbow_colors.pop() ## We can't lose violet! rainbow_colors.append("pink") # Pink's not in the rainbow! ``` We want `rainbow_colors` to be **immutable** - the list _cannot_ be changed. How we do that in Python? --- ## Introducing: Tuples **Sets** have the following properties: - No duplicates - Mutable **Tuples** are similar to a list with the following differences: - Allows duplicates (same as a list) - Once assigned, the tuple _cannot be changed_ ```python rainbow_colors_tuple = ("red", "orange", "yellow", "green", "blue", "indigo", "violet") ``` When should you use a tuple? - When you need data protection through immutability (note: all Python variables are public). - When you never want to change the list. - Tuples are sometimes wrapped in a class namespace to simulate what would be done with a [const structure](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-constants) in a C-based language. - This is a way of holding appconstants, or constants your program will use (like the API endpoint of a server, credentials, etc.) --- ## Tuple Syntax - Created with parentheses `()`. - Access values via indices (like regular lists, but *not* like sets). ```python rainbow_colors_tuple = ("red", "orange", "yellow", "green", "blue", "indigo", "violet") print(rainbow_colors[1]) # Prints "orange" ``` - Tuples can be printed with a `for` loop (just like a set or list!). ```python rainbow_colors_tuple = ("red", "orange", "yellow", "green", "blue", "indigo", "violet") for color in rainbow_colors_tuple: print(color) ``` --- ## We Do: Tuples Let's declare a tuple named `seasons` and set it to have the values `fall`, `winter`, `spring`, and `summer`. We'll print the tuple and each value. Then we'll try to reassign them (we can't)! --- ## Quick Review: Sets, Tuples, Lists **List**: - The original, normal object: `["red", "red", "yellow", "green"]`. - Has duplicates; mutable: `append()`, `insert(index)`, `pop()`, `pop(index)` **Set**: - List without duplicates: `{"red", "yellow", "green"}`. - Mutable: `add()` and `remove(element)` **Tuple**: - Has duplicates, but immutable: You can't change it! - `("red", "red", "yellow", "green")` will *always* be `("red", "red", "yellow", "green")`. --- ## Quick Review: Sets, Tuples, Lists ```python ### Creation ### # List my_list = ["red", "yellow", "green", "red"] # Sets my_set = {"red", "yellow", "green"} my_set2 = set(my_list)) my_set = set(a_list_to_convert) # Tuples my_tuple = ("red", "yellow", "green") ### Appending a New Value ### my_list.append("blue") my_set.add("blue") # Tuples -> You can't! ### Removing items: ### my_list.pop(1) my_set.remove("red") # Tuples -> You can't! ``` --- ## Introducing Types Variables certainly can hold a lot! - Sets, tuples, and lists are easily confused. - `type()` tells us what a variable is: set, tuple, list, dictionary, integer, string - anything! Try it: --- ## You Do: List Types Practice Create a local file, `sets_tuples.py`. In it: - Create a list (`[]`), set (`{}`), and tuple (`()`) of some of your favorite foods. - Create a second set from the list. Next, in every list type that you can: - Add `"pizza"` anywhere; append `"eggs"` to the end. - Remove `"pizza"`. - Re-assign the element at index `1` to be `"popcorn"`. - Remove the element at index `2` and re-insert it at index `0`. - Print the element at index `0`. Print your final lists using a loop, then print their types. Don't throw an error! --- ## Summary and Q&A We've learned two new types of lists: Sets: - A mutable list without duplicates. - Handy for storing emails, usernames, and other unique elements. ```python email_set = {'my_email@gmail.com', 'second_email@yahoo.com', "third_email@hotmail.com"} ``` Tuples: - An immutable list that allows duplicates. - Handy for storing anything that won't change. ```python rainbow_tuple = ("red", "orange", "yellow", "green", "blue", "indigo", "violet") ``` --- ## Additional Reading - [Repl.it that recaps Tuples](https://repl.it/@GAcoding/python-programming-tuple-practice?lite=true) - [Python Count Occurrences of Letters, Words and Numbers in Strings and Lists-Video](https://www.youtube.com/watch?v=szIFFw_Xl_M) - [Storing Multiple Values in Lists](https://swcarpentry.github.io/python-novice-inflammation/03-lists/) - [Sets and Frozen Sets](https://www.python-course.eu/sets_frozensets.php) - [Sets](https://www.learnpython.org/en/Sets) - [Python Tuple](https://www.programiz.com/python-programming/tuple) - [Tuples](http://openbookproject.net/thinkcs/python/english3e/tuples.html) - [Strings, Lists, Tuples, and Dictionaries Video](https://www.youtube.com/watch?v=19EfbO5D_8s) - [Python Data Structures: Lists, Tuples, Sets, and Dictionaries Video](https://www.youtube.com/watch?v=R-HLU9Fl5ug)