阿攀的博客

海阔天空

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  5 随笔 :: 2 文章 :: 11 评论 :: 0 Trackbacks

map的成员函数没有提供这一功能,对于这个问题,我首先想到的方法是,循环遍历一下,将其中每个元素和比较对象进行比较,就可以了,代码如下(为了方便说明,我将key的类型定义为int,对于其他类型的或是自定义类型的,可能需要自己写比较函数)

 1 map<intint>testMap;
 2 
 3 for (int i = 1; i < 11++i)
 4 {
 5    testMap.insert(make_pair(i, i+100));
 6 }
 7 
 8 int nCount = 0;
 9 for (itor = testMap.begin(); itor != testMap.end(); ++itor)
10 {
11    if (itor->first < 5)
12    {
13      ++nCount;
14    }
15 }

但是,在网上常看到很多高手都会给我们这样的忠告,在处理STL容器的时候,尽量不要自己去写循环处理。
在STL中,count_if这个算法,正符合我们的要求,而我们只需要提供比较函数就可以了,代码如下:
 1 template<class key, class Value>
 2 class cmp_less
 3 {
 4 public:
 5     cmp_less(key K)
 6         :nKey(K)
 7     {
 8 
 9     }
10 
11     bool operator()(pair<key, Value> elems)
12     {
13         if (elems.first < nKey)
14         {
15             return true;
16         }
17         else
18         {
19             return false;
20         }
21     }
22 private:
23     key nKey;
24 };
25 
26 nCount = count_if(testMap.begin(), testMap.end(), cmp_less<intint>(5));
文章写到这里也能结束了,但这几天在看bind2nd这个仿函数和别人文章的时候,想改用bind2nd试试,也看看自己掌握的情况,不用不知道,在写代码的时候才发现自己掌握的比较肤浅,尝试了大半天,侯捷老师的STL源码剖析一书也翻了好几次,总算写出来,代码如下:
 1 template<class Key, class Value>
 2 class myless : public binary_function<pair<Key, Value>, Key, bool>
 3 {
 4 public:
 5     bool operator()(pair<Key, Value> elemnt, Key other) const
 6     {
 7         if (elemnt.first < other)
 8         {
 9             return true;
10         }
11         else
12         {
13             return false;
14         }
15     }
16 };
17 
18 nCount = count_if(testMap.begin(), testMap.end(), bind2nd(myless<intint>(), 5));

在这之前我写出了这样的代码,

1 nCount = count_if(testMap.begin(), testMap.end(), bind2nd(less<pair<intint>>(), make_pair(5100)));

这样也可以比较,但有个问题,因为这样写是两个pair比较,而pair比较是这样的,请看源代码:

1 template<class _Ty1, class _Ty2> 
2 inline bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right)
3 {    // test if _Left < _Right for pairs
4    return (_Left.first < _Right.first ||
5            !(_Right.first < _Left.first) && _Left.second < _Right.second);
6 }

不仅比较key,还要比较value,这样必须把右边pair的value的值设的够大才行,这不符合我们要求,我们只要求key做比较。
bind2nd源代码是这样的,请看:

1 template<class _Fn2, class _Ty>
2 inline binder2nd<_Fn2> bind2nd(const _Fn2& _Func, const _Ty& _Right)
3 {    // return a binder2nd functor adapter
4    typename _Fn2::second_argument_type _Val(_Right);
5    return (std::binder2nd<_Fn2>(_Func, _Val));
6 }

我们注意到这句代码typename _Fn2::second_argument_type _Val(_Right);
就是右边的值(即做比较的值)要能向_Fn2::second_argument_type转换,而且是由_Fn2提供的,_Fn2::second_argument_type是什么呢,请看

1 template<class _Arg1, class _Arg2, class _Result>
2 struct binary_function
3 {    // base class for binary functions
4     typedef _Arg1 first_argument_type;
5     typedef _Arg2 second_argument_type;
6     typedef _Result result_type;
7 };

first_argument_type是左边参数类型,second_argument_type是右边参数类型,由于是map左边是pair,右边我们要求是key的类型,即int,所以我们
的定义这样的

1 template<class Key, class Value>
2 class myless : public binary_function<pair<Key, Value>, Key, bool>
3 



就这三个方法,个人感觉还是第二个比较好。



 

posted on 2009-03-08 23:37 阿攀 阅读(2201) 评论(2)  编辑 收藏 引用 所属分类: STL

评论

# re: 统计map中key小于某类型变量的个数 2009-03-09 15:26 liu755775
good  回复  更多评论
  

# re: 统计map中key小于某类型变量的个数 2009-05-02 23:18 尹东斐
这个解法很好,在lambda没有诞生之前,c++只能这么写,很折磨人。
如果用boost::lambda的话,这个问题就可以写成:

map<int, int> testMap;
testMap[1] = 3;
testMap[2] = 3;
testMap[4] = 3;
testMap[6] = 3;

int nCount = count_if(testMap.begin(), testMap.end(), bind(&pair<const int, int>::first, _1) < 5); // nCount == 3.  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理