我试图用c ++制作这个频率表,我的代码在下面。
#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <cassert>
using namespace std;
typedef std::pair<std::string, int> mypair;
struct IntCmp {
bool operator()(const mypair &lhs, const mypair &rhs) {
return lhs.second < rhs.second;
}
};
string removeSpaces(string input) {
input.erase(std::remove(input.begin(),input.end(),' '),input.end());
input.erase(std::remove(input.begin(), input.end(), '\t'), input.end());
input.erase(std::remove(input.begin(), input.end(), '.'), input.end());
return input;
}
void printmap(const std::map<std::string,int> &mymap, int size) {
std::vector<mypair> myvec(mymap.begin(), mymap.end());
assert(myvec.size() >= size);
std::partial_sort(myvec.begin(), myvec.begin() + size, myvec.end(), IntCmp());
for(int i = size; i --> 0;) {
std::cout << myvec[i].first << " " << myvec[i].second << "\n";
}
}
int main() {
string str;
cout << "Enter text:\n";
cin >> str;
cout << "Frequencies:\n";
str = "do be do bo.";
str = removeSpaces(str);
int size = str.size();
string *array = new string[size];
for(int i = 0; i < size; ++i) {
array[i] = str[i];
}
sort(array, array+size);
map<int, string> mymap;
for(int i = 0; i < size; ++i) {
mymap[i] = array[i];
}
map<string, int> freq;
for(int i = 0; i < size; ++i) {
if(freq.count(mymap[i]) == 0) {
//Not found
freq[mymap[i]] = 1;
}
else {
//Found
freq.at(mymap[i]) = freq.at(mymap[i]) + 1;
}
}
int mapsize = freq.size();
printmap(freq, mapsize);
}
当我运行str
给定为do be do bo.
的代码时,输出如下
o 3
d 2
b 2
e 1
所以这是我的思考过程。
我接受输入str
并将其放入数组中,并按字母顺序对该数组进行排序,然后将该数组放入映射mymap
。然后,我取mymap
并获取每个字符串的频率,并将字母作为键,频率作为地图freq
中的值。然后,我使用printmap()
函数按值降序排列地图。
然而,当我这样做时,键是随机排序的。因此,例如,在上面显示的字符串中,b 2
会在d 2
之后打印出来,即使我将freq
地图提供给printmap()
函数时它们是有序的
基本上,我正在寻找一种方法来按值排序printmap()
函数中的地图,然后按键排序,因此结果将按降序值和字母键打印出来。
do be do bo.
的理想结果如下:
o 3
b 2
d 2
e 1
感谢。
答案 0 :(得分:3)
不确定为什么你在这里使用std::partial_sort
- 它仅用于排序部分输入。请尝试std::stable_sort
:它会对输入进行排序,但不会影响比较相等的元素的顺序。这可以为您提供所需内容,因为您的输入map
已经按字母键增加排序:
struct IntCmp {
bool operator()(const mypair &lhs, const mypair &rhs) {
return lhs.second > rhs.second; // note reversed comparison here to sort by descending order
}
};
void printmap(const std::map<std::string,int> &mymap, int size) {
std::vector<mypair> myvec(mymap.begin(), mymap.end());
assert(myvec.size() >= size);
std::stable_sort(myvec.begin(), myvec.end(), IntCmp());
// note we now iterate forwards because the sort comparison is reversed
for(const auto &item : myvec) {
std::cout << item.first << " " << item.second << "\n";
}
}
或者,您可以更改比较函数以比较值和键,并使用普通std::sort
:
struct IntCmp {
bool operator()(const mypair &lhs, const mypair &rhs) {
if(lhs.second == rhs.second) return lhs.first < rhs.first; // this is the "secondary" comparison, used if the frequencies are equal
return lhs.second > rhs.second; // note reversed comparison here to sort by descending order
}
};
void printmap(const std::map<std::string,int> &mymap, int size) {
std::vector<mypair> myvec(mymap.begin(), mymap.end());
assert(myvec.size() >= size);
std::sort(myvec.begin(), myvec.end(), IntCmp());
// note we now iterate forwards because the sort comparison is reversed
for(const auto &item : myvec) {
std::cout << item.first << " " << item.second << "\n";
}
}