WHAT ARE PYTHON DATA STRUCTURES?
In Python we have 4 built-in data structures. You have probably heard of lists and dictionaries (the two most common data structures), but we also have sets and tuples. A data structure is a way for us to store an arbitrary number of elements or values into a variable, sometimes directly and sometimes indirectly.
LISTS
Below you will see a quick declaration/assignment of a list.
cars = ["telsa", "ford", "toyota", "honda"]
Notice how we declare our variable cars, and then use square brackets to denote that this will be a list. Afterwards we directly added 4 vehicles, but we should be aware that we can add as many vehicles as or as few vehicles as we want. There is also another way to declare a list, but it differs from using square bracket notation in that it has different functionality.
"""Another way to declare a list""" cars2 = list()
In the second method we are using a constructor to declare a list. However, this way is much better suited for type casting an already existing iter-able object (or an object/data type that can be iterated through). The elements or values in this list all must have a location for Python to properly work with them. Just like strings, lists have an index, starting from 0 that represents an element position in the structure. The element “tesla” lives at index 0, “ford” at index 1, “toyota” at index 2, and “honda” at index 3. This does not change the length of the list in anyway, the list remains at a length of 4. So to work with lists indirectly, we can use methods (behaviors that belong to a specific data type/object).
fruits = ["apple", "pear", "kiwi"] # Declaring the list # this selects then prints index 0 or the "apple" print(fruits[0]) # this adds an element to the end of a list fruits.append("banana") # this removes a specified element and permanently throws it away fruits.remove("pear") # this method also removes an element but saves it for us to use (popping the "apple" out) fruits.pop(0) # this is a manual way to permanently delete an element del fruits[1] # this allows us to insert an object at the specified index fruits.insert(0, "mango") # this method permanently reverses a list fruits.reverse() # this method clears the list out completely fruits. Clear() # this method returns a number, representing the index of the "kiwi" fruits.index("kiwi") # this method permanently sorts a list alphabetically with numbers first fruits.sort() # this method counts the amount of times "kiwi" appears in the list can be used to find duplicates fruits.count("kiwi") # this method allows us to append the list with more than one element fruits.extend(["lemon", "lime", "grapes"]) # this method takes a copy of the list (allowing us to escape the referenced memory location) fruits.copy()
Now that we have covered lists and all the associated methods, lets discuss what makes all of this indirect manipulation possible. Because this list is mutable (can be altered indirectly), we can use all of the syntax above. If a data structure is immutable, we cannot alter it in any way except directly, which requires going into the brackets and adding, changing, or removing elements. Let us now quickly discuss some other popular functions and manipulations of this data structure.
fruits = ["apple", "orange", "kiwi"] fruits2 = ["banana", 'lime', "lemon"] # this function returns the length of the list (3) len(fruits) # this compares the two lists length (will return True) print(len(fruits) == len(fruits2)) # this creates a list "fruits3" with both lists combined fruits3 = fruits + fruits2 # a non-permanent way to sort a list sorted(fruits) # this is a list with two nested lists inside of it shooping_list = [[“cheese”, “crackers”, “bread”], [“hand soap”, “shampoo”, “conditioner”]]
for loop
This is a loop that only runs for the specified number of times, all though not exclusive to just collections, its primary use case is looping through one.
fruits = ["apple", "orange", "kiwi"] # This will iterate through each element (this is traditional for loop) # for the first loop, item becomes "apple", then second loop "orange" and the third loop, item #becomes "kiwi for item in fruits: print(item) """lets run a for loop to change each element to its plural form using range""" # this tells the loop to run the length of fruits (3), 1st loop i=0, 2nd loop i=1 etc for i in range(len(fruits)): fruits[i] = fruits[i] + "s" # using selector to update # this list or elements are now plural print(fruits) ['apples', 'oranges', 'kiwis']
Tuples and Sets
Tuples are identical to a list except they cannot be changed as they are immutable. This makes them a static data type as opposed to a dynamic data type. We use tuples to store data that should not be changed, for example, the dimensions of my smart phone will never change so I would store it inside of a tuple. Because of the static nature of the tuple, it is also faster and more memory efficient. To declare one, we would use round bracket notation or parentheses.
fruits = ("apple", "orange", "kiwi") # notice the round brackets? this is a tuple!
Sets are declared with curly bracket notation, and they are similar in that they are used to store and arbitrary amount of elements, However they do not allow duplicates and the existing elements are unordered (no index) and cannot be changed. Sets do however allow for elements to be indirectly removed and added making it semi-mutable.
# Regarding the second 98, Python will automatically remove this duplicate ages = {23, 45, 67, 98, 98}
Dictionaries
We now know that lists have an element and an associated index number/position. Dictionaries allow us to provide a key instead of an index number. This essentially allows us to map our values and is what makes them so important as it allows us to dynamically use keys to access values versus static and non-negotiable index numbers.
cars = {"toyota": "tacoma", "chevy": "corvette", "honda": "civic"}
So, again when we want to access a value, we can simply input the key. Behind every dictionary key, sits a value. So how can we manipulate this dictionary? Just like lists we are going to use methods, functions, etc.
cars = {"toyota": "tacoma", "chevy": "corvette", "honda": "civic"} # this is how we manually select a key:value pair print(cars["ford"]) # this is how we add to a dictionary cars["ford"] = "f250" # this is how we delete manually del cars["ford"] # this updates the value (cannot have duplicate keys) cars["ford"] = "f150" # this pops out the chevy and returns its value (corvette) cars.pop("chevy") # this pops out the chevy and returns both key and value (chevy and corvette) cars.popitem("chevy") # this is how we select a value with a method (returns none if the key doesnt exist) cars.get("ford") # returns a tuple of all key:value pairs cars.items() # returns a tuple of all keys cars.keys() # returns a tuple of all values cars.values() # allows us to add an arbitrary amount of key:value pairs to the end of the dictionary cars.update({"tesla": "model x", "dodge": "ram"}) # allows us to cop and escape memory reference cars.copy() # clears the list completely and permanently cars.clear()
Functions
cars = {"toyota": "tacoma", "chevy": "corvette", "honda": "civic"} cars2 = {"dodge": "ram", "lexus": "lx470"} # prints the length of the dictionary print(len(cars)) # this creates a zip object that can be iterated through (really should be used during the loop declaration) x = zip(cars, cars2) # using the constructor to create a dictionary cars3 = dict(nissan="armada", lincoln="navigator") # this is how we concatenate dictionaries cars4 = cars | cars2 | cars3
for looping through a dictionary:
cars = {"toyota": "tacoma", "chevy": "corvette", "honda": "civic"} # looping through both key:value for key, value in cars.items(): if key == "chevy": cars[key] = "chevy1" # looping through just values for value in cars.values(): print(value) # looping through keys is by default for key in cars: print(key)