Hello again! In this video, we are going to continue looking at removing algorithms. As is often the
case, there are other versions of remove().
There is remove_if(), which takes a predicate, and _copy() versions, which will write the result
to a destination container,
instead of modifying the iterator range in place.
The remove() algorithm uses the equality operator to decide whether to remove an element. With remove underscore
if(), we can provide our own predicate as the third argument.
This will be called with each element as the argument. And then, if this returns true, the element
will be removed.
And if it returns false, the element will be kept.
In this example, we want to remove elements which are exactly divisible by 3, and keep the rest.
The return value will be an iterator, again, to the first [removed] value, and we can pass that as a argument
to erase().
So here is some code.
We have our vector.
We have the call to remove_if(), with the callable object as the third argument.
Then we have the iterator as the return value. And then we call erase(), using that iterator.
So we get a result in which the elements 3 and 9 have been removed, because they are divisible
by 3.
But the others have been kept.
remove_copy() will write the results to a destination. It will write the data from this is iterator range
into this destination, but it will omit any elements which have this value.
So this will populate "vec2" with all these elements, except for the ones which have the value 1.
If you remember the copy_if() algorithm, we could get that to do the same thing by copying all the
elements which are not equal to 1.
So these two are the same, but with the logic inverted. In this one, we say that 1 is the value we
do not want to copy. In this.
we say that anything except 1 is the value that we want to copy.
So let's try this out. We have our call to remove_copy().
So this will remove the elements with the value 1.
Then we have the equivalenct code with copy_if()
So this will copy everything except the elements with value 1.
So let's see what we get.
So the new vector has those elements, without the elements with value one.
And there is also remove_copy_if() which combines both these.
It will take a lambda expression and do a copy of all the elements for which the expression is [true].
So that would give us a container in which the elements are, 1, 4, 1, 5.
So here is our call to remove_copy_if().
There is the lambda expression. And there is the equivalent code using copy_if().
So this will populate the container with all the elements which are not exactly divisible by 3.
The other main algorithm is unique().
This will remove duplicate elements, but they have to be adjacent.
So this means that the elements in the iterator range must be sorted. Otherwise, unique() will not work properly.
This has the similar behaviour, in that elements are only "logically" removed from the container and not physically
removed.
If we wants to physically remove them, we pass the returned iterartor to erase().
So we have code like this. We have our vector.
We sort it, and then we call unique(). We get an iterator to the first removed element, and then
we pass that to erase().
So there is our original vector.
There is the sorted vector. It has an adjacent duplicates element, so that gets moved to the back
of the container.
And then we call erase(), and that element is destroyed.
So the result is the elements, in order, without the duplicate elements with value 1.
Unique uses the equality operator. We can also provide our own predicate for deciding what constitutes
being a duplicate.
The predicate will take 2 arguments, which correspond to successive elements. So this could be,
for example, the first and second, or the second and third elements in the container.
And in this case, we want to remove elements which differ by one.
So if we have 3, followed by 4, then we want to remove the elements with value 4.
So there is our call to unique().
Again, we have sorted the vector.
(Do not forget that!)
So we call unique with our predicate, and then we call erase() on the return value.
So what do you think we will get?
(Just go back to our original vector.)
So there is our original version: there it is, sorted. 1 is followed by 1, which is not more than 1.
1 is followed by 3, which is not one more than 1. 3 is followed by 1, which is one more
than 3.
So 4 gets moved to the end of the container and now 3 is followed by 5, which is not one
more.
And 5 is followed by 9, which is not one more.
So this will only remove the element with value
4.
It keeps the elements with value 5.
And again, we have the _copy version, which writes the result to a destination.
So this will do the copy, but omit any duplicate elements.
And we can also call it with a predicate.
So here is the unique copy version.
So this just copies the result, without the duplicate value 1.
And this is the version with the predicate.
So this will populate a new container with the result that we had before.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!