我有这个小程序,它读取一行输入&打印其中的单词,以及它们各自的出现次数。我想根据它们的出现情况对地图中存储这些值的元素进行排序。我的意思是,只出现一次的单词将被命令在开头,然后是出现两次的单词等等。我知道谓词应该返回一个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;
}
答案 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() );