The container std::map
always sorts keys based on their value. 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.
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:
std::map<int,int,cntBitsCmp> myMap= {
{128,2},
{3,4},
...
};
Here is a demo on ideone. It correctly orders 128 ahead of 3, because 3 has two bits set, while 128 has only one.
Since C++11, you can also use a lambda expression instead of defining a comparison function. If you combine this with std::bitset::count instead of using your own counting function, then the code becomes rather short:
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 Sergey, I'm assuming 32-bit integers for the sake of clarity. Please adapt the code to your needs.
Code on Ideone
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With