C++学习笔记-map使用注意事项总结

近期找了家实习,要求实现日志文件的统计,统计需求为每个小时uid的活跃时长和全天内所有uid活跃时长的分布情况,log文件中存在session跨小时和交叉的情况。由于没有接触过日志文件,也没有实际使用过C++进行开发,一上来就有些蒙圈,就先想到的就是使用纯纯的结构体去完成,但开发量太大了,还没有办较好的监控session交叉的情况,最后调研发现map可以较好的完成此功能。但是想到就要考虑log文件本身的情况了,每一条记录都是按照出现的时间排序的,但是map本身内部使用红黑树实现,所以会自动按照key进行排序,这样就会导致新的map中的时间是乱序的,对后续处理session交叉很不利,因此考虑使用unordered_map。但是unordered_map只有gcc4.4版本以上才支持,本地的服务器只有gcc358,调研得知unordered_map是c++11标准里的,对于c98是没有的。map的方法中其实有四个参数,原型如下:

template < class Key, class T, class Compare = less<Key>,class Allocator = allocator<pair<const Key,T> > > class map;

key和value是大家熟知的,第三个参数是用于指定排序的方法的,但是只针对于key的方法,可以重新定义key的实现排序方式(此处有一个大胆的想法,如果均返回bool类型的ture或false是否可达到无序的效果,待明天实验一下),对于第四个参数知道是用来定义存储分配模型的。在使用时我们的key和value的值是可以自己定义的,即可以指定为数据类型,比如在我的这个开发中,我将sessionId和Uid组合的字符串作为了key,对于value我自己定义了一个结构体,用于存放uid,start_time和end_time,具体形式如下:

std::map<string, elemnt_value> active_hour_element;
struct elemnt_value {
	std::string uid;
	int start_time;
	int end_time;
};

说到这里想先说一下map增加元素的注意事项,在使用insert方法时会检查是否已经出现key值,如果map中存在该key值则插入失败,所以当想实现出现相同的key则更新原有数据时要使用数组赋值的形式。通常在我们建立完map,数据处理完成后我们要访问输出map中的数据,此时要借助与迭代器,代码如下:

active_hour_element.insert("123_456",s1);//检测key是否存在,如果存在操作失败
active_hour_element[123_456]=s1;//如果key存在则覆盖原值
std::map<std::string, element_value>::iterator index;
for(index=active_hour_element.begin();index!=active_hour_element.end();index++){
    cout<<index->first<<endl;//输出key
    cout<<index->second.uid<<"\t"<<index->second.start_time<<"\t"<<index->second.end_time<<endl;//输出元素
}

简单应用过后,谈一谈如何让map按照我们想要的方式存储,排序方式实际是函数对象:即调用操作符的类,它们是行为类似函数的对象。表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个 类,其实质是对operator()操作符的重载,实现比较简单,但map只实现了对<的重载,如果没有重载key的排序方式,默认是按照key值升序排序,下面我们来制定按照key降序排序和字符串的长度递增排序。排序方法实现:

#include<map>
#include<string>
#include<iostream>
using namespace std;
using std::pair;
 
typedef pair<string, int> PAIR;

class Comp {
	bool operator()(const elemnt_value& lhs, const elemnt_value& rhs) {
		return lhs < rhs;
	}
};//重载的排序方法

template <class T> struct down : binary_function <T,T,bool> {
  bool operator() (const T& lhs, const T& rhs) const
    {return lhs>rhs;}
};//按照key值倒序排序


struct CmpByKeyLength {
  bool operator()(const string& lhs, const string& rhs) {
    return lhs.length() > rhs.length();
  }
};//按key值的长度递减排序
 
 
int main() {
  std::map<std::string, int, down<std::string> > name_map;
  name_map["LiMin"] = 90; 
  name_map["ZiLinMi"] = 79; 
  name_map["BoB"] = 92; 
  name_map.insert(make_pair("Bing",99));
  name_map.insert(make_pair("Albert",86));

  std::map<std::string, int>::iterator iter;

  for ( iter= name_map.begin(); iter != name_map.end();++iter) {
    cout << iter->first<<"\t"<<iter->second << endl;
  }

  std::map<std::string, int, down<std::string> > name_map_length;
  name_map_length["LiMin"] = 90; 
  name_map_length["ZiLinMi"] = 79; 
  name_map_length["BoB"] = 92; 
  name_map_length.insert(make_pair("Bing",99));
  name_map_length.insert(make_pair("Albert",86));

  std::map<std::string, int>::iterator index;

  for ( index= name_map_length.begin(); index!= name_map_length.end();++index) {
    cout << index->first<<"\t"<<index->second << endl;
  }


  return 0;
}

map排序的方式只能按照key实现,如果想要按照value或value中某一字段排序,需要借助于其他线性结构实现,比如vector或者list,我借助了vector实现,具体的步骤为,建立一个vector,元素的类型为pair类型,将map的元素都存入vector中,然后使用sort指定为自定义的排序方法排序,代码片段如下:

using std::pair;//必须指定,否则不能识别pair类型
typedef pair<std::string, elemnt_value>  PAIR;

std::vector<PAIR> active_hour_sort(active_hour_element.begin(), active_hour_element.end());//定义vector并使用map初始化

struct CmpByStart {
	bool operator()(const PAIR& lhs, const PAIR& rhs) {
		return lhs.second.start_time < rhs.second.start_time;
	}
};

void sort_map_all(vector<PAIR>& sort_sarttime) {
	//vector<PAIR>sort_sarttime(active_hour_element.begin(), active_hour_element.end());
	sort(sort_sarttime.begin(), sort_sarttime.end(), CmpByStart());
}

总结:map会自动按照key进行字典升序排序,如果想要按照key的其他形式排序可以自行定义函数对象实现,即重载operator()操作符。如果想要按照value或者value的某一字段排序需要借助于vector等线性可操作的数据结构。参考博文如下:http://blog.csdn.net/iicy266/article/details/11906189

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值