【问题标题】:C++ Sort Map By Value Numerically, Key AlphabeticallyC++ 按数值、键字母顺序对映射进行排序
【发布时间】:2015-07-17 02:48:40
【问题描述】:

我正在尝试用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);
}

当我使用do be do bo. 给出的str 运行代码时,输​​出如下

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

谢谢。

【问题讨论】:

标签: c++ sorting


【解决方案1】:

不知道您为什么在这里使用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";
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多