【问题标题】:predicate for a map from string to int从字符串到整数的映射谓词
【发布时间】:2011-04-18 19:02:01
【问题描述】:

我有一个小程序,它读取一行输入并打印其中的单词,以及它们各自的出现次数。我想根据它们的出现对存储这些值的地图中的元素进行排序。我的意思是,只出现一次的单词将被排序在开头,然后出现两次的单词 7 依此类推。我知道谓词应该返回一个布尔值,但我不知道参数应该是什么。它应该是地图的两个迭代器吗?如果有人可以解释这一点,将不胜感激。提前谢谢你。

#include<iostream>
#include<map>

using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::map;

int main()
{
    string s;
    map<string,int> counters;   //store each word & an associated counter

    //read the input, keeping track of each word & how often we see it
    while(cin>>s)
    {
        ++counters[s];
    }

    //write the words & associated counts
    for(map<string,int>::const_iterator iter = counters.begin();iter != counters.end();iter++)
    {
        cout<<iter->first<<"\t"<<iter->second<<endl;
    }

    return 0;
}

【问题讨论】:

    标签: c++ map predicate


    【解决方案1】:

    std::map 始终根据其键排序。您不能按元素的值对元素进行排序。

    您需要将内容复制到另一个可以排序的数据结构(例如std::vector&lt;std::pair&lt;string, int&gt; &gt;)。

    这是一个谓词,可用于对这样的vector 进行排序。请注意,C++ 标准库中的排序算法需要一个“小于”谓词,它基本上表示“小于 b”。

    bool cmp(std::pair<string, int> const &a, std::pair<string, int> const &b) {
      return a.second < b.second;
    }
    

    【讨论】:

    • 我会补充一点,有一个简洁的语法可以做到这一点:std::vector&lt;std::pair&lt;string, int&gt; &gt; v(counters.begin(), counters.end());
    • 那么这是否意味着地图不带谓词?如果这是一个愚蠢的问题,请原谅我,我还是个学生。
    • 您可以给 std::map 一个谓词作为类型参数,但该谓词用于对键进行排序,而不是对值进行排序。 std::map 需要排序谓词,因此它可以提供快速查找。
    【解决方案2】:

    您不能使用地图,它的顺序是预定义的(默认情况下,从键类型上的std::less 开始)。解决您的问题的最简单方法是创建一个 std::multimap&lt;int, string&gt; 并在其中插入您的值,然后循环遍历 multimap,它将按键类型(int,出现次数)排序,这将为您提供顺序你想要的,而不必定义谓词。

    【讨论】:

      【解决方案3】:

      您将无法通过 std::map 一次性完成此操作。一次只能对一件事进行排序,并且您不能就地更改密钥。我建议使用您现在拥有的代码来维护 counters 映射,然后使用 std::max_element 和比较映射中每个 std::pair&lt;string, int&gt;second 字段的比较函数。

      【讨论】:

        【解决方案4】:

        地图的键是排序的,而不是值。这就是地图高效的原因。如果不使用其他数据结构(可能是反向索引!),您无法按出现次数对其进行排序。

        【讨论】:

          【解决方案5】:

          如前所述,它根本行不通——地图始终按其键值(即字符串)排序。

          正如其他人所指出的,您可以将数据复制到其他结构,并按值排序。另一种可能性是改用Boost bimap。我之前发过demo的基本思路。

          【讨论】:

            【解决方案6】:

            您可能希望将map&lt;string,int&gt; 转换为vector&lt;pair&lt;const string, int&gt; &gt;,然后对 int 成员上的向量进行排序。

            你可以的

            struct PairLessSecond
            {
              template< typename P >
              bool operator()( const P& pairLeft, const P& pairRight ) const
              {
                return pairLeft.second < pairRight.second;
              }
            };
            

            您也可以使用带有绑定的 lambda 以某种方式构造所有这些。

            现在

               std::vector< std::map<std::string,int>::value_type > byCount;
               std::sort( byCount.begin(), byCount.end(), PairLessSecond() );
            

            【讨论】:

              猜你喜欢
              • 2019-02-17
              • 2021-11-15
              • 1970-01-01
              • 1970-01-01
              • 2016-08-09
              • 1970-01-01
              • 1970-01-01
              • 2017-06-21
              • 1970-01-01
              相关资源
              最近更新 更多