How do I change the map container's internal sorting scheme?

余生颓废 提交于 2021-01-29 03:30:53

问题


I'm a beginner C++ programmer so there are language constructs that I don't understand which prevents me from understanding map's API (for your reference, here)

More to the point, some questions:

How do I change the internal sorting scheme of map so that, given that we're working with map::<string, ...>, the key values are sorted alphabetically?

More specifically about the map::key_comp, is it a define-and-forget thing where once we define what it means for two elements of the same type to be "unequal (one is less than the other)", then the sorting is done internally and automatically - so all we need to is insert key/value pairs? Or do we have to define equality/ordering and then call the function explicitly to return a boolean to implement ordered insertion?


回答1:


Here's an example of how you give the sorted map a template argument to use a non-default sort:

std::map<int, int, std::greater<int> > m;

Taken from C++ std::map items in descending order of keys

Also, for a more complex example: how to declare custom sort function on std::map declaration?




回答2:


[Solved] Solution I'd chosen

Suppose your map was: map<int,vector<int>,compAB> myMap;

Then you need to do 2 things to define "compAB":

Define a comparison function that returns true or false/(or 1 or 0). I haven't tested whether this function can take multiple arguments (although I don't see why it can't so long as it returns a bool. This function should specify how you intend to order two objects of the same type as the key value in your your map.

bool compare(int a, int b)
{
    if(a < b) return true; 
    return false; //Default
}

The API for the map::key_comp object (here indicates that the comparison function needs to return true if the first argument is "less than"/"comes before" the second argument. It should return false otherwise source). Here, I've used a simple criteria for determining "less than": a precedes b if a<b, as the computer evaluates it.

Create a struct whose member consist of just an operator-overload:

struct compAB
{
   bool operator()(int i1, int i2){
      return compare(i1, i2); 
   }
};

Then, you can make the declaration: map<int,vector<int>,compAB> myMap; and any calls to insertion() will insert the pairs you've indicated according to the key-ordering scheme you specified

For instance:

#include <iostream> 
#include <map> 

bool compare_descend(int a, int b)
{
    //specifies that when a>b return true -> a FOLLOWS b
    if(b < a) return true; 
    return false; 
}

bool compare_ascend(int a, int b)
{
    //specifies that when a<b return true -> a PRECEDES b
    if(a < b) return true; 
    return false; //Default
}

struct comp_asc
{
   bool operator()(int i1, int i2)
   {
     return compare_ascend(i1, i2); 
   }
};


int main()
{   
    std::cout << "int_map_asc: [key,value]\n"; 

    //Map declaration via class function
    std::map<int,std::string,comp_asc> int_map_asc; 

    //Insert pairs into the map
    int_map_asc.insert( std::pair<int,std::string>(0, "Alan") );
    int_map_asc.insert( std::pair<int,std::string>(1, "Baye") );
    int_map_asc.insert( std::pair<int,std::string>(2, "Carl") );
    int_map_asc.insert( std::pair<int,std::string>(3, "David") );

    //Iterate & print
    std::map<int,std::string,comp_asc>::iterator a_it; 
    for(a_it=int_map_asc.begin(); a_it!=int_map_asc.end(); a_it++)
           std::cout << "[" << a_it->first << "," << a_it->second << "]\n"; 



    std::cout << "\nint_map_desc: [key,value]\n"; 

    //Map declaration via function pointer as compare
    bool(*fn_compare_desc)(int,int) = compare_descend; //Create function ptr to compare_descend()
    std::map<int,std::string,bool(*)(int,int)> int_map_desc(fn_compare_desc); //fn ptr passed to constructor

    //Insert pairs into the map
    int_map_desc.insert( std::pair<int,std::string>(0, "Alan") );
    int_map_desc.insert( std::pair<int,std::string>(1, "Baye") );
    int_map_desc.insert( std::pair<int,std::string>(2, "Carl") );
    int_map_desc.insert( std::pair<int,std::string>(3, "David") );

    //Ititerate & print
    std::map<int,std::string,bool(*)(int,int)>::iterator d_it; 
    for(d_it=int_map_desc.begin(); d_it!=int_map_desc.end(); d_it++)
        std::cout << "[" << d_it->first << "," << d_it->second << "]\n"; 

    return 0; 
}

Output:

int_map_asc: [key,value]
[0,Alan]
[1,Baye]
[2,Carl]
[3,David]

int_map_desc: [key,value]
[3,David]
[2,Carl]
[1,Baye]
[0,Alan]

Additional examples here.



来源:https://stackoverflow.com/questions/35247239/how-do-i-change-the-map-containers-internal-sorting-scheme

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!