简体   繁体   English

如何在 std::map 声明中声明自定义排序函数?

[英]How can I declare a custom sort function on std::map declaration?

The container std::map always sorts keys based on their value.容器std::map总是根据它们的值对键进行排序。 Is it possible to make it sort, for example, on the number of bits set upon declaration?例如,是否可以根据声明时设置的位数对其进行排序?

I have a function for counting set bits:我有一个计算设置位的功能:

for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i, value >>= 1) {
  if ((value & 1) == byteState) ++num_bits;
}

But I do not know how to apply it when declaring the map:但是我不知道在声明地图时如何应用它:

std::map<int, int> myMap = {
  {1,2},
  {3,4},
  //...
}

I've tried to put it as a third parameter in the declaration <int,int,decltype(countSetBits)> , but with no luck.我试图将它作为声明中的第三个参数<int,int,decltype(countSetBits)> ,但没有运气。

You need to wrap your function in a binary operator, like this: 您需要将函数包装在二元运算符中,如下所示:

#include <iostream>
#include <map>
#include <algorithm>

int cntBits(int value) {
    int num_bits=0;
    for(size_t i = 0; i < 32 ; ++i, value >>= 1) {
        if ((value & 1) == 1) ++num_bits;
    }
    return num_bits;
}

struct cntBitsCmp {
    bool operator()(int a, int b) {
        return cntBits(a) < cntBits(b);
    }
};

Now you can use cntBitsCmp in a declaration: 现在您可以在声明中使用cntBitsCmp

std::map<int,int,cntBitsCmp> myMap= {
    {128,2},
    {3,4},
    ...
};

Here is a demo on ideone . 这是关于ideone演示 It correctly orders 128 ahead of 3, because 3 has two bits set, while 128 has only one. 它在3之前正确地命令128,因为3有两个位设置,而128只有一个。

Basically this could work as you want: 基本上这可以按你的意愿工作:

bool comp(int x , int y ){
    return  __builtin_popcount(x) <  __builtin_popcount(y);
}
int main(){
    bool(*fn_pt)(int,int) = comp;
    std::map<int, int, bool(*)(int,int) > myMap (fn_pt);
    myMap[7]=11;
    myMap[8]=12;
    cout<<myMap.begin()->first<<endl;  // you get 8 instead of 7
}

Since C++11 , you can also use a lambda expression instead of defining a comparison function. C ++ 11开始 ,您还可以使用lambda表达式而不是定义比较函数。 If you combine this with std::bitset::count instead of using your own counting function, then the code becomes rather short: 如果将它与std :: bitset :: count结合使用而不是使用自己的计数函数,则代码变得相当短:

auto comp = [](int a, int b) { return std::bitset<32>(a).count() < std::bitset<32>(b).count(); };
std::map<int, int, decltype(comp)> m(comp);

Note: Similar to the solution by dasblinkenlight, I'm assuming 32-bit integers for the sake of clarity. 注意:类似于dasblinkenlight的解决方案 ,为了清楚起见,我假设32位整数。 Please adapt the code to your needs. 请根据您的需求调整代码。

Code on Ideone Ideone上的代码

When I wrapped my function in a binary operator and used it sort my map via the length of the strings (key) all was well and it worked.当我将我的函数包装在一个二元运算符中并使用它通过字符串(键)的长度对我的地图进行排序时,一切都很好并且它工作正常。 However, what I did not realise is that it affected the maps find() function.但是,我没有意识到它影响了 maps find() 函数。 Instead of finding the key that is equal to the string it would instead find the key that has the same string length as the key!而不是找到等于字符串的键,而是找到与键具有相同字符串长度的键!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM