 Hello everyone. This video is about the map abstract data type. So abstract data types are big concepts and data structures and computer science. And the map is like the unordered list, the stack, the queue, the deck, it exists in every language. And here we're going to talk about it in the context of Python. So like a previous video, this video is also an excerpt from something I recorded earlier. And this video follows on our video about the Python dictionary. So if you watch that, you're in good shape. If you didn't watch it, you're going to see that I pick up some code from some exercises that I did in the Python dictionary video. So you may want to follow along on that Python dictionary video if you haven't already. And I will turn it over now to my younger self. The dictionary itself, though, remember the Python dictionary is a data type. It implements the concept of a map abstract data type. And remember abstract data types are like these big high level concepts that transcend programming language, that transcend implementation. You have maps in Java, you have maps in C++, you have maps in all sorts of language. In Python, the map abstract data type is implemented as concretely as the dictionary data type. So what do you need to know about maps? They're a collection of key value pairs where keys are unique identifiers, right? You can only have one unique key, right? Values are associated with the key. You can put things in a key, or excuse me, you can put things in a map. You can get things out of a map. You can delete things from a map, you can get a size, and you can test if some things are in the map, right? So these are the things that you need to know how to do with a map or a dictionary, right? So why do you care about it? Why do you want to use a map? They're really useful for looking up complex objects by an ID, right? So we did students, right? We had a student name and what we got was their ID back. But you could store whatever you wanted to to be associated with that key, right? So we could define a whole student class. Why don't we do it? Let's not just talk about it. Let's do it. Let's define a class called student, right? And we need to put a constructor, right? And let's do first name, last name, student ID, okay? And we'll do self.first gets first, self.last gets... Oh, I called it name, sorry, self.student ID gets student ID, okay? So I've defined this class student. I probably should have defined a string, and that's okay. We can put in our students, right? Let's say that what we want to have is a dictionary that looks up students, in the concept of a student, by their 8.5.0 number. So let's say that students sub 8.5.0, 1, 2, 3, 4, 5, 6 gets the new student Leslie, nope, and her 8.5.0, 1, 2, 3, 4, 5, 6. Yeah, yeah. So we're storing her 8.5.0 twice, right? But what are we doing here? Student is our own data type. It stores a bunch of different information about Leslie, no. And if we look, we can actually see it's put this thing in here, right? Here's students at size one. I've got one student in here named Leslie, no. And this is what information I've stored about her. So I can look her up later and just ask myself, hey, tell me all about the student with this 8.5.0 number, and I'm going to get a student object back. Now, I didn't create a string method for her, or a wrapper method, so I can't put in her out easily. But I can do things like, now that I've assigned her to variable, I can get her first name, I can get her last name, and I can get her student ID, right? So, but what's in the dictionary? The dictionary has a key, 8.5.0, 1, 2, 3, 4, 5, 6, and then a bunch of values associated with it. In this case, the value is the student object, right? So what I can do is I can put complex objects in the dictionary and then look them up in big O of one time. That's the key, okay? The other thing a dictionary is really useful for is counting the occurrences of an item, right? So suppose you want to know, suppose you have a great big enormous file that's got lists of, say, birds and types of birds and when they were seen. You can keep a count of them as the value in a dictionary, right? So say that I had a great big long list from your mythology department and it said, I saw a blue jay at 9am and then a cardinal at 9.02 and then another blue jay at 9.03 and on and on and on for, say, a whole year. What you all you want to know is how many blue jays did they see? Well, what you can do is you can create a dictionary and you make the key, the name of the bird, bird sub blue jay and then every time the value that's associated with that bird is the number of times you have seen it, right? So the first time you see a bird, you put dictionary, is blue jay in the dictionary? No? Okay, let's put it there. Dictionary sub blue jay gets one. I've seen one bird. And then every time you encounter the word blue jay, you're like, oh yeah, I've seen that before. Let me just increment its counter. Very cool use of a dictionary. Now dictionaries are usually implemented using hash tables. In fact, that's what Python implements its dictionary with is a hash table. Because indexing the hash table is big O of one and hashing is big O of one, we achieve big O of one search time for a key. The downside is the list, the hash table is going to have those empty spaces, those spaces where things aren't being used, right? If you fill up the hash table, it gets expensive to resize it, right? Because resizing effectively means you've got to create a whole new table in memory and reinsert all your old values into it. And of course, you can have hash collisions and depending on your collision resolution strategy, if you're using linear probing, for example, you may wind up with clusters and you can start getting some inefficiencies in your hash table. Alright, so how do you implement a map, right? How would you implement a dictionary? Well, you're going to do it in assignment number seven. You are going to implement a very simple map implementation. And you're going to use a hash table. So the way you're going to do it is you are going to have two lists, okay? One list for the keys, one list for the values. They're going to be the same length. So for example, 127 slots or open spaces, right? What you do is you take the key. So your two operations are putting something in and getting something out of the dictionary. And you assign a value to a key in the dictionary. What you will do is you hash the key to one of the indexes down here, right? So if you want to associate, say, Joe with the value 62, right? Let me type in a note here, right? So EG students sub Joe gets 62. What you wind up doing is you hash Joe. And let's just assume for sake of argument, it hashes to index four, okay? So you put the key Joe in the keys list at index four. And then you put the value 62 at the same index that Joe hashed to, but in the value list. So you've got two arrays here, two lists, one called keys and one calls value. You hash the key, find out where it goes in the key list, which is here. And then you put the value in the same index of the values. This is what you would call a parallel list or a parallel array, right? But this is a hash table, right? You kind of have two tables here, the keys and the values, and you're hashing to the keys and then putting it in the same value. Then later, if you want to get the value out, right? You hash the key again to see where is it? Oh, it's at index four. They want the value that's at index, they're key of Joe. Let me return to them 62, right? Now, as you go to implement it, this is kind of the data structure you're going to use. So you will implement a hash map data type. Think of it as your version of a Python dictionary. Why are you doing it if the dictionary is already there? Well, I want you to understand and appreciate how the data structure works for a hash table. So I'm going to give you the hash function. I'm going to tell you what it needs to be. You can use any form of collision resolution that you wish, right? So if two things hash to index 10, right? Say Eric hashes the index 10. How do you resolve that? I don't care. You can use linear probing. You can use quadratic probing. You can use chaining. It's entirely up to you to decide. So you're going to implement a very basic map data type. And then you're going to use it in an experiment. So get yourself familiar with the dictionary and how it works. And then that will tell you what's expected of you when you go to implement the hash map yourself. All right? So that's it. Play around with the map or, excuse me, play around with the Python dictionary. And we'll work on assignment seven. That's what's due this Sunday at 1159. Hopefully it's a shorter assignment. But don't wait until the last minute because you do have to implement a hash table to support it. Let me know if you have any questions about that. And I'll talk to you in the next lecture.