Filter a map in C++
This post will discuss how to filter a map in C++.
We may want to filter a map based on some criteria, such as the key, the value, or both. For example, we may want to create a new map that contains only the key-value pairs where the key is even, or where the value is greater than some integer, or where the key and the value are both odd.
1. Using erase() function
The recommended approach to filter a map is to use the erase() function from the std:: class. This function removes an element or a range of elements from a map. We can use the erase() function to filter a map by removing the elements that do not satisfy our criteria.
To use the erase() function to filter a map, we need to provide an iterator pointing to an element to be removed from the map. For example, the below program filters the even keys from the map using an iterator-based while loop and the erase() function.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> #include <map> int main() { std::map<int, char> map = { {1, 'A'}, {2, 'B'}, {3, 'C'}, {4, 'D'} }; /* filter all even keys */ auto it = map.begin(); while (it != map.end()) { if (it->first % 2 == 1) { map.erase(it++); // Special note: Use post-increment here } else { ++it; } } for (const auto &entry: map) { std::cout << "{" << entry.first << ", " << entry.second << "}" << '\n'; } return 0; } |
Output:
{2, B}
{4, D}
Note that the iterator pointing to the removed element will be invalidated by the erase() function. To handle this, pass the post-increment iterator to the erase() function. This increments the iterator but passes a copy of the original iterator to the erase() function. Also note that it is not possible to filter elements using the std::remove_if function from associative containers like std::map.
2. Using std::copy_if algorithm
Another way to filter a map in C++ is to use the std::copy_if algorithm from the <algorithm> header. This algorithm copies the elements from one range to another range if they satisfy a given predicate. A predicate is a function or a functor that returns a boolean value based on some condition.
To use the std::copy_if algorithm to filter a map, we need to provide four arguments: the beginning and the end of the source range (the original map), the beginning of the destination range (the new map), and the predicate. For example, if we want to create a new map that contains only the key-value pairs where the key is even, we can do something like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <iostream> #include <map> #include <algorithm> // Define a function that returns true if the key is even bool is_even(const std::pair<int, int> &p) { return p.first % 2 == 0; } int main() { std::map<int, char> map = { {1, 'A'}, {2, 'B'}, {3, 'C'}, {4, 'D'} }; /* filter all even keys */ // Create an empty destination map std::map<int, char> m; // Copy the elements from the source map to the destination map if they // satisfy the predicate std::copy_if(map.begin(), map.end(), std::inserter(m, m.begin()), is_even); for (const auto &entry: m) { std::cout << "{" << entry.first << ", " << entry.second << "}" << '\n'; } return 0; } |
Output:
{2, B}
{4, D}
The std::copy_if algorithm is very convenient to use, but it requires us to create an empty destination map before copying the elements. Also, it requires us to provide an iterator that inserts the elements into the destination map. This can be done by using the inserter() function from the <iterator> header, which returns an iterator that calls insert on the destination map for each element.
We can also define custom functions or functors to filter a map and pass them as arguments to the copy_if() function. A functor is an object that can be called as a function by using the operator(). We can define a functor like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream> #include <map> #include <algorithm> // Define a functor that returns true if the key is even struct is_even { bool operator()(const std::pair<int, int> &p) const { return p.first % 2 == 0; } }; int main() { std::map<int, char> map = { {1, 'A'}, {2, 'B'}, {3, 'C'}, {4, 'D'} }; std::map<int, char> m; std::copy_if(map.begin(), map.end(), std::inserter(m, m.begin()), is_even()); for (const auto &entry: m) { std::cout << "{" << entry.first << ", " << entry.second << "}" << '\n'; } return 0; } |
Output:
{2, B}
{4, D}
Custom functions and functors are very flexible and reusable for defining predicates for filtering maps. We can use them to specify any condition based on the key, the value, or both.
That’s all about filtering a map in C++.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)