map和vector的查找方法
在写程序的时候,需要经常在map或者vector中查找符合条件的记录,而在map和vector中都没有提到查找函数。在本文中,详细说明了find_if用在map和vector中的用法。
我们首先看下在STL中find_if是怎样实现的,然后就能写出针对各种类型的find_if函数.
//定义在STL实现代码stl_algo.h中 template <class InputIterator, class Predicate> InputIterator find_if(InputIterator first, InputIterator last,Predicate pred) { while (first != last && !pred(*first)) ++first; return first; } |
可见STL是把find_if定义为一个函数模板,该函数模板接收两个数据类型,InputItearator是输入的迭代器,Predicate是用于比较的函数或者函数对象(仿函数)。这里有个问题需要注意,那就是为什么这里要将比较函数定义为函数对象呢?这个问题在下面进行分析下。
1.map的查找方法
如果给定map的一个second值,要求在该map中找出与之相符的map索引,则需要使用STL的算法find_if来查找,而find_if的比较函数需写为函数对象。下面是一个示例:
//用于map比较的函数对象 class CMapFindIf { public: CMapFindIf(string szFindString):_szFindString(szFindString){}; ~CMapFindIf(){}; public: bool operator()(map<string,string>::value_type &it) { //TODO:这里写比较函数的算法,如果认为和给定值相符,则返回true,否则返//回false return it.second == _szFindString; } private: string _szFindString; }; |
这个用于比较的函数对象实际上重载了()运算符,因为在find_if函数中是这样调用该函数对象的pred(*first)),实际上是将它作为一个bool key_comp() 函数使用的,在函数对象中的()运算符的形参类型是比较对象的value_type,是因为find_if中传入*first的缘故。而value_type到底是什么类型,下面有相信定义。
上面给出了仿函数的写法,下面是针对map的find_if使用方法。
map<string, string> _m_FileAcceptExeName; char szBuf[100];//查找值 if( find_if(_m_FileAcceptExtName.begin(),_m_FileAcceptExtName.end(), CMapFindIf(string(szBuf))) != _m_FileAcceptExtName.end() ) return true; else return false; |
在stl_map.h头文件中定义有以下的map::value_type 。可见map的value_type是pair类型的数据类型。
template <class Key, class T, class Compare, class Alloc = alloc> class map { public: // typedefs: typedef Key key_type; typedef T data_type; typedef T mapped_type; typedef pair<const Key, T> value_type; typedef Compare key_compare; private: typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type; rep_type t; // red-black tree representing map public: typedef typename rep_type::pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typename rep_type::reference reference; typedef typename rep_type::const_reference const_reference; typedef typename rep_type::iterator iterator; typedef typename rep_type::const_iterator const_iterator; typedef typename rep_type::reverse_iterator reverse_iterator; typedef typename rep_type::const_reverse_iterator const_reverse_iterator; typedef typename rep_type::size_type size_type; typedef typename rep_type::difference_type difference_type; ........ }; |
map的iterator的定义是在stl_tree.h中,定义如下:
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc = alloc> class rb_tree { protected: typedef void* void_pointer; typedef __rb_tree_node_base* base_ptr; typedef __rb_tree_node<Value> rb_tree_node; typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator; typedef __rb_tree_color_type color_type; public: typedef Key key_type; typedef Value value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef rb_tree_node* link_type; typedef size_t size_type; typedef ptrdiff_t difference_type; ...... }; |
2.vector的查找方法
vector的查找这里有两种方法,一个是定义查找函数,另一个是定义仿函数。
if ( vto.size() == 1 && find_if(vto.begin(), vto.end(),find_qq) != vto.end() ) { //TODO: } bool find_qq(string &szMail)//find_qq(vector<string>::value_type ) { if ( szMail.find("@qq.com") != string::npos ) return true; return false; } |
上面的vector查找方式是调用函数的查找,仅能查找符合某一条件的数据,而在实际情况中可能需要查找不同条件的数据,所以此处我们也使用函数对象(仿函数)方法实现一个。
class CVecFindFun { public: CVecFindFun(string szFindString):m_szFindString(szFindString){} ~CVecFindFun(){} private: string m_szFindString; public: //bool operator() (string &vecValue) bool operator() (vector<string>::value_type &vecValue) { if ( vecValue == m_szFindString ) return true; else return false; } }; |
template <class T, class Alloc = alloc> class vector { public: typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type* iterator; typedef const value_type* const_iterator; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; ....... }; |
2.map插入时的排序
把比较函数写成函数对象才可以的,比如:
class CompEr { public: bool operator()(const string& ls, const string& rs) const { return ls < rs; } }; typedef std::map<string, int, CompEr> mymap; int main(int argc, char* argv[]) { //TODO: return 0; } |
posted on 2008-02-20 10:19 kevin.Tian 阅读(15599) 评论(0) 编辑 收藏 举报