比较器返回在 C++ 中的真正含义是什么

问题描述

我正在尝试在 C++ 中进行稳定排序,而我的数组是这样的

{{first = "art zero",second = "let3 "},{first = "own kit dig",second = "let2 "},{first = "art can",second = "let1 "}}

sort(let.begin(),let.end(),[](pair<string,string>& a,pair<string,string>& b) {
    int comp = a.first.compare(b.first);
    if(!comp) {
        return a.second.compare(b.second);
    } else {
        return comp;
    }
});

为什么第一个值没有按字典顺序排序?返回值在 C++ 比较器中的真正含义是什么?谢谢

解决方法

如果您只是选择 std::map 作为您的容器,则默认排序提供词汇排序顺序的存储,例如

#include <iostream>
#include <string>
#include <map>

int main (void) {
    
    std::map<std::string,std::string> let {{"art zero","let3 "},{"own kit dig","let2 "},{"art can","let1 "}};
    for (const auto& p : let)
        std::cout << p.first << "," << p.second << '\n';
}

示例使用/输出

$ ./bin/map_sort_lex
art can,let1
art zero,let3
own kit dig,let2

不能同时使用 map/mutimap

如果您必须同时对 .first.second 进行电报排序,则不能使用 std::map/std::multimap。它们仅限于对 .first 进行排序以进行存储。另一种方法是使用 std::vector<std::pair<>> 和您的字符串对。

您可以通过编写一个简单的 bool Compare 函数来实现您的自定义比较,如下所示:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

bool lexcmp (const std::pair<std::string,std::string>& lhs,const std::pair<std::string,std::string>& rhs)
{
    if (lhs.first != rhs.first)
        return lhs.first < rhs.first;
    
    return lhs.second < rhs.second;
}

int main (void) {
    
    std::vector<std::pair<std::string,std::string>> let {{"art zero",{"art zero","let1 "}};
    
    std::sort (let.begin(),let.end(),lexcmp);
    
    for (const auto& p : let)
        std::cout << p.first << "," << p.second << '\n';
}

示例使用/输出

添加额外的 "art zero","let2 " 对以强制对 .second 进行排序后,您将:

$ ./bin/vector_sort_lex
art can,let2
art zero,let2

如果您只能对 .first 进行排序,那么 std::map(或 std::multimap)会为您处理排序。要同时对 .first.second 进行排序,那么上面的解决方案也不错。

,

std::pairstd::string 已经默认提供字典顺序,所以您不需要为此任务编写比较函数

如果您确实想编写一个比较函数,它必须满足 Compare 要求。它必须提供严格的弱排序。这意味着如果第一个值出现在第二个之前,则返回 true,否则返回 false

您可以修复您的代码,使其在“小于”时返回 true,否则返回 false

sort(let.begin(),[](const pair<string,string> &a,const pair<string,string> &b){
    int comp = a.first.compare(b.first);
    if (comp == 0) {
        return a.second.compare(b.second) < 0; // less than (ascending order)
    } else
        return comp < 0; // less than (ascending order)
});