如何构造可全局使用的自定义Comparator比较器函数?
通用比较器可行性结论
可以构造适配绝大多数场景的通用比较器,核心思路是将取值逻辑、比较规则抽离为可配置的参数,不需要为不同容器类型、不同排序规则单独编写重复的比较函数,C++11及之后的版本借助泛型编程、lambda表达式可以非常便捷地实现。
常见场景的通用比较器实现(C++示例)
通用降序/升序比较器
标准库已经内置了通用的比较器模板,不需要自己手动实现:
- 升序排序默认使用
std::less<T>(),匹配sort函数的默认行为 - 降序排序直接使用
std::greater<T>(),支持任意实现了>运算符的类型
// 示例:对vector<int>降序排序 std::vector<int> vec = {3,1,4,2,5}; std::sort(vec.begin(), vec.end(), std::greater<int>());
按容器第N个元素排序的通用实现
适配vector of list、vector of tuple、vector of array等需要取指定位置值排序的场景:
// C++14及以上版本可直接使用泛型lambda实现 auto cmpByNth = [](size_t index, bool ascOrder = true) { return [index, ascOrder](const auto& containerA, const auto& containerB) { // 取两个容器指定位置的值比较 auto valA = *std::next(containerA.begin(), index); auto valB = *std::next(containerB.begin(), index); return ascOrder ? valA < valB : valA > valB; }; }; // 调用示例:对vector<std::list<int>>按第二个元素(索引为1)升序排序 std::vector<std::list<int>> listVec = {{1,3}, {2,1}, {3,2}}; std::sort(listVec.begin(), listVec.end(), cmpByNth(1)); // 按第二个元素降序排序的调用方式 std::sort(listVec.begin(), listVec.end(), cmpByNth(1, false));
map元素排序的通用实现
map本身默认按key升序排序,如果需要自定义排序规则,通常会把map元素转存到vector中再用通用比较器排序:
std::map<int, std::string> mp = {{1, "banana"}, {2, "apple"}, {3, "cherry"}}; std::vector<std::pair<int, std::string>> vec(mp.begin(), mp.end()); // 示例:按map的value值降序排序 std::sort(vec.begin(), vec.end(), [](const auto& p1, const auto& p2) { return p1.second > p2.second; });
使用注意事项
- 比较器涉及的自定义类型需要提前重载对应比较运算符,或者在比较器内手动编写自定义类型的比较逻辑
- 自定义比较器必须满足严格弱序要求,不能出现
a < b和b < a同时为真的情况,否则会触发排序的未定义行为 - 如果你使用的C版本低于C14不支持泛型lambda,可以将比较器封装为模板结构体,同样可以实现通用效果
内容的提问来源于stack exchange,提问作者Kalash Jain
相关产品推荐
相关产品推荐

