轉自:http://www.cnblogs.com/motadou/archive/2009/02/01/1561549.html
有時我們要在map、vector容器中查找符合條件的記錄,map提供一個find的成員函數,但也僅限於查找關鍵字滿足條件的記錄,不支持值域的比較。如果我們要在值域中查找記錄,該函數就無能無力了。而vector甚至連這樣的成員函數都沒有提供。所以一般情況下進行值域的查找,要麼自己遍歷數據,要麼求助於STL的find_if函數。前種方法我們這裏就不贅述了,只講find_if函數。
template <class InputIterator,
class Predicate>
InputIterator find_if(InputIterator first, InputIterator last,Predicate pred)
{
while (first != last && !pred(*first)) ++first;
return first;
}
find_if是一個模板函數,接受兩個數據類型:InputItearator迭代器,Predicate用於比較數值的函數或者函數對象(仿函數)。find_if對迭代器要求很低,只需要它支持自增操作即可。當前遍歷到的記錄符合條件與否,判斷標準就是使得pred()爲真。至此可能還有些不是很明瞭,下面舉幾個例子實際操練下的它的用法。
假如我們有個map對象是這麼聲明的:
std::map<int, std::string> my_map; my_map.insert(std::make_pair(10, "china")); my_map.insert(std::make_pair(20, "usa")); my_map.insert(std::make_pair(30, "english")); my_map.insert(std::make_pair(40, "hongkong"));
插入值後我們想得到值爲”english”的這條記錄,要怎樣寫程序呢?下面是個範例參考下:
1 | #include <map> |
2 | #include <string> |
3 | |
4 | class map_finder |
5 | { |
6 | public: |
7 | map_finder(const std::string &cmp_string):m_s_cmp_string(cmp_string){} |
8 | bool operator ()(const std::map<int, std::string>::value_type &pair) |
9 | { |
10 | return pair.second == m_s_cmp_string; |
11 | } |
12 | private: |
13 | const std::string &m_s_cmp_string; |
14 | }; |
15 | |
16 | int main() |
17 | { |
18 | std::map<int, std::string> my_map; |
19 | my_map.insert(std::make_pair(10, "china")); |
20 | my_map.insert(std::make_pair(20, "usa")); |
21 | my_map.insert(std::make_pair(30, "english")); |
22 | my_map.insert(std::make_pair(40, "hongkong")); |
23 | |
24 | std::map<int, std::string>::iterator it = my_map.end(); |
25 | it = std::find_if(my_map.begin(), my_map.end(), map_finder("english")); |
26 | if (it == my_map.end()) |
27 | printf("not found\n"); |
28 | else |
29 | printf("found key:%d value:%s\n", it->first, it->second.c_str()); |
30 | |
31 | return 0; |
32 | } |
class map_finder即用於比較的函數對象,它的核心就是重載的()運算符。因爲每個容器迭代器的*運算符得到的結果都是該容器的value_type值,所以該運算符的形參就是map迭代器指向的value_type類型的引用。而map的value_type到底是什麼類型,就得看下STL的源代碼是如何定義的。
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc> class map { public: typedef Key key_type; typedef pair<const Key, T> value_type; ...... };
從上面的定義可以看出,map的value_type是std::pair<const Key, t>類型,它的first值就是關鍵字,second值保存map的值域。
vector的find_if用法與map的很相似,區別僅僅是二者的value_type不一樣而已。我們看下vecotr對value_type的定義。
template <class T, class Alloc = alloc> class vector { public: typedef T value_type; typedef value_type* iterator; ...... };
可以看出vector的value_type就是容器的值類型,瞭解了這點,我們做個vector的find_if示範。
1 | #include <vector> |
2 | #include <string> |
3 | |
4 | struct value_t |
5 | { |
6 | int a; |
7 | int b; |
8 | }; |
9 | |
10 | class vector_finder |
11 | { |
12 | public: |
13 | vector_finder(const int a):m_i_a(a){} |
14 | bool operator ()(const std::vector<struct value_t>::value_type &value) |
15 | { |
16 | return value.a == m_i_a; |
17 | } |
18 | private: |
19 | int m_i_a; |
20 | }; |
21 | |
22 | |
23 | int main() |
24 | { |
25 | std::vector<struct value_t> my_vector; |
26 | struct value_t my_value; |
27 | |
28 | my_value.a = 11; my_value.b = 1000; |
29 | my_vector.push_back(my_value); |
30 | |
31 | my_value.a = 12; my_value.b = 1000; |
32 | my_vector.push_back(my_value); |
33 | |
34 | my_value.a = 13; my_value.b = 1000; |
35 | my_vector.push_back(my_value); |
36 | |
37 | my_value.a = 14; my_value.b = 1000; |
38 | my_vector.push_back(my_value); |
39 | |
40 | std::vector<struct value_t>::iterator it = my_vector.end(); |
41 | it = std::find_if(my_vector.begin(), my_vector.end(), vector_finder(13)); |
42 | if (it == my_vector.end()) |
43 | printf("not found\n"); |
44 | else |
45 | printf("found value.a:%d value.b:%d\n", it->a, it->b); |
46 | |
47 | getchar(); |
48 | return 0; |
49 |