谓词从字符串到int的映射

时间:2011-02-07 15:32:52

标签: c++ map predicate

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

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

6 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:1)

您无法使用地图,它的订单是预定义的(默认情况下,来自密钥类型的std::less)。对你的问题最简单的解决方案是创建一个std::multimap<int, string>并在那里插入你的值,然后循环遍历多图,这将按照键类型(int,出现次数)排序,这将给你您想要的顺序,而不必定义谓词。

答案 2 :(得分:0)

使用std::map的一次传球你无法做到这一点。它一次只能对一件事进行排序,而且您无法就地更改密钥。我建议您使用现有的代码来维护counters地图,然后使用std::max_element和比较函数来比较每个second的{​​{1}}字段地图。

答案 3 :(得分:0)

地图的键已排序,而不是其值。这就是让地图高效的原因。您不能在不使用其他数据结构的情况下按事件排序(可能是反向索引!)

答案 4 :(得分:0)

如上所述,它根本不起作用 - 地图始终按其键值排序,这将是字符串。

正如其他人所说,您可以将数据复制到其他结构,并按值排序。另一种可能性是使用Boost bimap代替。我之前发布了demo基本想法。

答案 5 :(得分:0)

您可能希望将map<string,int>转换为vector<pair<const string, int> >,然后对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() );