Hello again! In this video, we are going to look at the C++ map.
This is another associative container. In the set,
the elements just consisted of the key and nothing else. In a map,
the elements actually have two parts.
There is the key, and a so-called "value".
These are stored as a pair object.
And the first member of the pair is the key,
and the second member is the value of the element.
Again, the keys have to be unique.
We cannot have two elements with the same key, but we can have two elements which have the same value,
provided
the keys are different.
And again, they are stored in a tree, in order, using the less-than operator of the key.
The value of the pair is used to store the data for that element, and the key is used to locate it.
Normally there is some kind of relationship between the key and the value.
For example, if we have a map of the company's staff, we could have the employee number as the key
and their personnel record as the data.
If we have a map of results from a sporting event, we could have the name of the competitor as the
key, and their result in the event as the value.
When we use a map, we search for a particular key.
So one of these. And then we get an element, and we look up the data, from the value member of the element.
So the key acts as an index for the map.
This is very similar to a "hash map" or a "directory" in other languages.
The structure will look like this.
We have two parts to the element, the key and the value.
So here we have the key, which is presumably a job level, or a pay grade, and the value is a job description.
So these are all organized depending on the key.
The value is not taken into account.
So "Driver" is greater than "Analyst", but that does not matter.
All that matters is that 42 is less than 67.
As with set, we can use insert() and erase() for adding and removing elements. The element type is
a pair, so we need to provide a pair object as the argument to insert.
And typically we use make_pair().
The first argument to make_pair() is going to be the key of our new element.
And the second member is going to be its value. In C++11,
we can also use list initializers, so we can put the key and value inside a pair of braces.
And again, the keys have to be unique.
So if we try to insert an element, and there is already an element in the map which has the same key,
then this will fail. And we check for that exactly the same way as we did in the set: we get a paper
object returned. The second member is a bool, which will tell us if it succeeded.
So we include the header.
We create an empty map object.
This is going to have a key of type string and a value of type int.
And then we add some elements to it.
We first call make_pair(), to show how to do that.
So this is going to create a new element, with key "Maybelline" and value 86. And then using the list
initializer.
This is going to have the key "Graham" and the value 78.
And then we can use this function to print them out.
It takes a map by reference to const and then we have a range for loop.
So, all pretty straightforward, I hope.
And then we have the same logic as we did in the set example.
We try to add another element, which has the same key as an element that is already in the map.
We get a pair object returned from the call to insert().
The second member will tell us if it succeeded.
And the first member will be an iterator to this element, which made it fail, or the new element if it succeeded.
This is iterator is actually going to be an iterator to an object of the element type, which is a pair.
So this is actually going to be a pair itself.
And the first member is going to be the key of this element.
And the second member is going to be the value of the element.
Then we remove the element which has this key.
And then we try to insert it again. And this time it should succeed.
So there is our initial map elements.
They are in alphabetical order, the order of the keys. "Graham" comes before "Maybelline". Then we try
to add another element with key "Graham". The map already has one.
So the map is not modified.
Then we remove the element with key "Graham", and then we try to add our element again.
So this time we have a new element, with key "Graham" and score 66.
Map has a feature which the set does not.
And that is subscript access to elements.
However, it does work differently from the way that we are used to, with strings, vectors and arrays.
So we put the name of the map, and then square brackets. And this will finish the element, which
has this argument as its key, and it will return the value of that element.
So this will return the value of the element with key "Graham". If we assign to this, then this will update
the value of that element.
So Graham now has the score
66.
However, if we put something in here, and there are no elements in the map which already have
that argument as key, then this will create a new element, and this will be the key of that element.
So this will now create a new element with key "Grace", and set its value to 66.
So if the element does not already exist, it will be created. If the elements does exist,
it willl overwrite the existing value of the element.
So let's try this out.
So we are starting off with the same map as we had before, with the same initial elements. Then we use
subscripts, to access Graham's value.
Then we set Graham's value to 66, and then we see what happens when we search Grace's score to 66.
So those are the original elements.
We get Graham's score, which is 78.
Then we set Graham's score to 66.
So it has done that.
And then we add Grace with a score of 66.
So we now have this new element for Greece.
And you will see that the elements are still in alphabetical order.
There are still ordered.
And also that we can have two elements with the same value and different keys.
We can call the find() and count() member functions, as we did with the set.
So here we call find() to get Graham's score, and we call count() to get the number of "Graham"'s in
the map.
We saw with the set that we are not allowed to modify the returned element from the find().
So let's see if we can do this with map.
And no, we cannot!
Lots of compiler errors!
But maybe it is just the key which is the problem?
So let's see if we can change the value.
Yeah, so you can do that, so we can change Graham's scores to 67.
So we found an element with key "Graham", and we set its score to 67.
And there is one element.
So you can modify the value of a map element, but not the key.
And with algorithms, we have the same constraint again.
We can use algorithms provided they only reach each iterators for a map, and they do not try to modify them
or rearrange them.
So we have our call to find_if(). This is going to take an element object as argument.
So this needs to be a pair, of string and int, because that is what the elements of the map are.
And then we have our lambda expression, which will compare the key to "Graham".
And similarly for count_if().
So we get the same results as we did with the member functions.
And maps have the same strengths and weaknesses as sets. They can search or locate an element very quickly.
Inserting and removing elements is usually very fast, unless you are unlucky and the tree has to rebalance.
The main application for maps is for data, which has an index of some kind.
For example, with a contact list, you could have the contact's name as their key, and then the data
would be their phone number or email address or some other data.
The employee records with the employee ID as the key and the record as the value. Results from a database
query.
Quite often, you have a row with an index, so you could use the index as the key and the rest of the
row as the data. And so on.
They are also useful for storing data which naturally falls into key-value pairs.
So things like JSON and XML.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!