C++ remove, remove_copy, remove_if and remove_copy_if function use detailed explanation

If you don't know the specific scene, that is, what kind of container the element is stored in, you cannot remove the element from the sequence. Therefore, "remove elements" algorithms cannot do this, they only overwrite selected elements or ignore copied elements. The removal operation does not change the number of elements in the sequence of "removed" elements.

There are 4 removal algorithms:

  • remove() can remove objects equal to the third parameter from the sequence specified by its first two forward iterator parameters. Basically every element is removed by covering it with the elements behind it. It will return an iterator to the position after the new last element.
  • remove_copy() can copy the elements in the sequence specified by the first two forward iterator parameters to the destination sequence specified by the third parameter, and ignore the elements equal to the fourth parameter. It returns an iterator to the next position of the last element copied to the destination sequence. The sequences cannot be overlapping.
  • remove_if() can remove elements from the sequence specified by the first two forward iterators that can make the predicate as the third parameter return true.
  • remove_copy_if() can copy the elements in the sequence specified by the first two forward iterator parameters that can make the predicate as the fourth parameter return true to the destination sequence specified by the third parameter. It returns an iterator to the next position of the last element copied to the destination sequence. The sequences cannot be overlapping.


You can use remove() as follows:

 
std::deque<double> samples {1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0};
samples.erase(std::remove(std::begin(samples), std::end(samples), 0.0), std::end(samples));
std::copy(std::begin(samples),std::end(samples), std::ostream iterator <double> {std::cout," "});
std::cout << std::endl;
// 1.5 2.6 3.1 4.1 6.7

The sample should not contain a physical measurement value of 0. The remove() algorithm will overwrite other elements by shifting them to the left. In this way, the randomly distributed zeros can be eliminated. The iterator returned by remove() points to the end of the new sequence obtained by this operation, so it can be used as the starting iterator of the deleted sequence to call the member function erase() of samples. The comment indicates that the elements in the container have not been changed.

If you want to keep the original sequence and generate a copy after removing the selected elements, you can use remove_copy(). E.g:

 
  1. std::deque<double> samples {1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0}; std::vector<double> edited_samples;
  2. std::remove_copy(std::begin(samples), std::end(samples), std::back_inserter(edited_samples), 0.0);

The non-zero elements in the samples container will be copied to the edited_samples container, which happens to be a vector container. These elements are added to edited_samples through the back_insert_iterator object, so this container only contains the elements copied from the sample.

remove_if() provides a more powerful ability to remove elements that match a given value from the sequence. The predicate determines whether an element is removed; it accepts an element in the sequence as a parameter and returns a Boolean value. E.g:

 
using Name = std::pair<string, string>; // First and second name
std::set<Name> blacklist {Name {"Al", "Bedo"}, Name {"Ann", "Ounce"}, Name {"Jo","King"}};
std::deque<Name> candidates {Name{"Stan", "Down"}, Name {"Al", "Bedo"}, Name {"Dan", "Druff"},Name {"Di", "Gress"}, Name {"Ann", "Ounce"}, Name {"Bea", "Gone"}}; candidates.erase(std::remove_if(std::begin(candidates), std::end(candidates),[&blacklist](const Name& name) { return blacklist.count(name); }), std::end(candidates)); std::for_each(std::begin(candidates), std::end(candidates), [] (const Name& name){std::cout << '"' << name.first << " " << name.second << "\" ";});
std::cout << std::endl; // "Stan Down" "Dan Druff" "Di Gress" "Bea Gone"

This code is used to simulate a candidate applying to become a club member. The names of those well-known restless people are kept in the blacklist, which is a collection. Candidates currently applying for membership are stored in the candidates container, which is a deque container. Use the remove_if() algorithm to ensure that no names in the blacklist will pass the selection process. The predicate here is a lambda expression that captures the blacklist container by reference. When the parameter exists in the container, the member function count() of the set container will return 1. The value returned by the predicate will be implicitly converted to a boolean, so for every candidate that appears in the blacklist, the predicate will return true, and then they will be removed from the candidates. The notes show the candidates who passed the selection process.

remove_copy_if() is to remove_copy() just like remove_if() is to remove. Here is how it works:

 
std::set<Name> blacklist {Name {"Al", "Bedo"}, Name {"Ann", "Ounce"}, Name {"Jo", ,"King" } };
std::deque<Name> candidates {Name {"Stan", "Down"}, Name { "Al", "Bedo"},Name {"Dan", "Druff"}, Name {"Di", "Gress"}, Name {"Ann", "Ounce"},Name {"Bea", "Gone"}};
std::deque<Name> validated;
std::remove_copy_if(std::begin(candidates) , std::end(candidates), std::back inserter(validated), [&blacklist] (const Name& name) { return blacklist.count(name); });

This code achieves the same function as the previous code, except that the result is stored in the validated container and the candidates container is not modified.

< C++ swap_ranges C++ fill和fill_n >

Guess you like

Origin blog.csdn.net/digitalkee/article/details/112447321