问题描述
我正在尝试在 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::pair
和 std::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)
});