1、map按照value排序
首先想到的是利用stl中的sort方法,但sort方法只能只能對線性容器進行排序(vector,list,deque),對於map這種關聯型容器
,會破壞數據結構,可以迂回下,把map中的元素放到vector中,並且自定義容器中元素的比較方法。
#include<string> #include<map> #include<vector> #include<iostream> #include<utility> #include<algorithm> //字符串分割函數 std::vector<std::string> split(std::string str, std::string pattern) { std::string::size_type pos; std::vector<std::string> result; str += pattern;//擴展字符串以方便操作 int size = str.size(); for (int i = 0; i < size; i++) { pos = str.find(pattern, i); if (pos < size) { std::string s = str.substr(i, pos - i); result.push_back(s); i = pos + pattern.size() - 1; } } return result; } int cmp(const std::pair<std::string,int> &pairIt1,const std::pair<std::string,int> &pairIt2) { return pairIt1.second > pairIt2.second; } int main(void) { std::string str_input; std::map<std::string,int> map_result; std::vector<std::string> split_result; std::vector< std::pair<std::string,int> > vector_sort; std::string tmp(","); getline(std::cin,str_input); std::cout << str_input << std::endl; split_result = split(str_input,tmp); int size = split_result.size(); for(int i=0;i < size;i++) { map_result[split_result[i]]++; std::cout << split_result[i] << std::endl; } std::map<std::string,int>::iterator obj = map_result.begin(); std::map<std::string,int>::iterator end = map_result.end(); for( ; obj!=end; obj++) { vector_sort.push_back(*obj); std::cout << obj->second << std::endl; } sort(vector_sort.begin(),vector_sort.end(),cmp); size = vector_sort.size(); for(int i = 0; i < size; i++) { std::cout <<vector_sort[i].first << " " << vector_sort[i].second << std::endl; } return 0; }
2、map按照key排序
首先map的模板定義為:
tempate <tepename _Key,typename _TP,typename _Compare=std::less<key>, typename _Alloc=std::allocator<std::pair<const _Key,_Ip>>> class map{ public: typedef _Key key_type; typedef _Ip mapped_type; typedef std::pair<const _Key,_Ip> typedef _Compare key_compare; typedef _Alloc allocator_type; };
可以看到map類模板有4個模板參數:_Key,_Tp,_Compare,_Alloc,其中_Compare與_Alloc已經有了默認參數。
其中less和greater是兩個關系類仿函數,可以用來指定key的順序,模板如下:
備注:binary_function可以作為一個二元函數對象的基類,它只定義了參數和返回值的類型,本身並不重載()操作符,這個任務應該交由派生類去完成。
template <class T> struct less : binary_function <T,T,bool> { bool operator() (const T& x, const T& y) const {return x<y;} }; template <class T> struct greater : binary_function <T,T,bool> { bool operator() (const T& x, const T& y) const {return x>y;} };
結論:
所以當我們打算定義map的key排序時,就必須在定義一個map類型對象的時候,指定一個有嚴格順序或者強序的Comapre類。
//自定義map的key排列順序 map<string,int,greater<string>> m1; struct myCompare { bool operator()(const string& l, const string& r)const { return l.length() > r.length(); } }; map<string,int,myCompare> m2;
3、自定義map不區分大小寫
通過自定義仿函數來實現不區分大小寫:
//方法1
struct NoCaseCompare{ bool operotor()(cosnt std::string& lhs,const std::string& rhs) cosnt { std::string s1(lhs); for(size_t i=0; i < lhs.size(); ++i) { if(s1[i] >= 'a' && s1[i] <= 'z'){ s1[i] -= 32; } } std::string s2(rhs); for(size_t i=0; i < rhs.size(); ++i) { if(s2[i] >= 'a' && s2[i] <= 'z'){ s2[i] -= 32; } } return s1.comapre(s2) >= 0 ? false : true; } }; map<string,int,NoCaseCompare> m_map;
//方法2
struct ci_less : std::binary_function<std::string, std::string, bool> { // case-independent (ci) compare_less binary function struct nocase_compare : public std::binary_function<unsigned char, unsigned char, bool> { bool operator()(const unsigned char &c1, const unsigned char &c2) const { return tolower(c1) < tolower(c2); } }; bool operator()(const std::string &s1, const std::string &s2) const { return std::lexicographical_compare(s1.begin(), s1.end(), // source range s2.begin(), s2.end(), // dest range nocase_compare()); // comparison } }; map<string, int, ci_less> m_map;
4、