【问题标题】:How can I declare a custom sort function on std::map declaration?如何在 std::map 声明中声明自定义排序函数?
【发布时间】:2013-03-13 09:03:11
【问题描述】:

容器std::map 始终根据键的值对键进行排序。是否可以对其进行排序,例如,根据声明时设置的位数?

我有一个计数设置位的功能:

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

但是在声明地图的时候不知道怎么应用:

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

我尝试将它作为第三个参数放在声明 &lt;int,int,decltype(countSetBits)&gt; 中,但没有成功。

【问题讨论】:

  • 如果它是一个普通函数,你还必须将它作为函数指针传递给构造函数。
  • 顺便说一句,gcc 有一组很好的builtins,其中一个int __builtin_popcount(unsigned int) 返回整数中设置的位数。

标签: c++ sorting dictionary


【解决方案1】:

当我将我的函数包装在一个二元运算符中并使用它通过字符串(键)的长度对我的地图进行排序时,一切都很好并且它工作正常。但是,我没有意识到它影响了 maps find() 函数。而不是找到等于字符串的键,而是找到与键具有相同字符串长度的键!

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

由于C++11,您也可以使用lambda expression 而不是定义比较函数。如果你将它与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);

注意:类似于solution by Sergey,为了清楚起见,我假设为 32 位整数。请根据您的需要调整代码。

Code on Ideone

【讨论】:

    【解决方案3】:

    基本上这可以随心所欲地工作:

    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
    }
    

    【讨论】:

      【解决方案4】:

      您需要将您的函数包装在一个二元运算符中,如下所示:

      #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);
          }
      };
      

      现在您可以在声明中使用cntBitsCmp

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

      这是demo on ideone。它正确地将 128 排在 3 之前,因为 3 设置了两个位,而 128 只有一个。

      【讨论】:

      • 您假设是 32 位整数。 while (i) {++n; i&amp;=i-1;}
      • @jthill 正确。我复制粘贴了 OP 的代码,并对其进行了修改以删除常量。我将代码作为示例发布,理解没有人会在不修改的情况下使用此代码。
      猜你喜欢
      • 2021-12-17
      • 2015-01-29
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 2020-10-07
      相关资源
      最近更新 更多