C ++按字母顺序按值排序地图,按字母顺序排列

时间:2015-05-06 19:16:14

标签: c++ sorting

我试图用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

感谢。

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