关联容器所需的比较器

Comparator needed for an associative container

本文关键字:比较器 关联      更新时间:2023-10-16

我需要一std::set<std::pair<std::string, int>, Compare>,根据它们的 int 值(以相反的顺序)比较两对,如果它们的 int 值相同,则根据它们的字符串值(以相同的顺序),但如果它们的字符串相等,那么两对被认为是相等的(无论它们的 int 值如何)。 所以我想出Compare课是:

struct Compare {
bool operator()(const std::pair<std::string, int>& a, const std::pair<std::string, int>& b) const {
if (a.first == b.first)
return false;
if (a.second > b.second)
return true;
if (a.second < b.second)
return false;
return a.first < b.first;   
}
};

测试内容

std::set<std::pair<std::string, int>, Compare> s;
s.insert({"Apple", 3}); 
s.insert({"Apple", 5}); 

工作正常(仅插入第一对)。 但

int main() {
std::set<std::pair<std::string, int>, Compare> s;
s.insert({"Ai", 14}); 
s.insert({"Am", 14}); 
s.insert({"F", 5}); 
s.insert({"Apple", 3}); 
s.insert({"Apple", 5}); 
}

显示{"Apple", 3}{"Apple", 5}都入,我不知道为什么。 我的Compare课上有什么逻辑错误? 它应该是什么? 我考虑使用std::map<std::string, int, Compare>但在这种情况下,比较器只能使用键类型std::string,这不足以满足我的规格。

我也试过:

bool operator()(const std::pair<std::string, int>& a, const std::pair<std::string, int>& b) const {
if (a.first < b.first || a.first > b.first) {
if (a.second > b.second)
return true;
if (a.second < b.second)
return false;
return a.first < b.first;
}
return false;
}

它仍然没有给出我想要的结果。

在检查了您的要求后,我得出的结论是,您比较对象的标准不符合严格周排序的要求。

假设您将以下对象插入到集合中:

std::pair<std::string, int> obj1 = {"F", 5};
std::pair<std::string, int> obj2 = {"Apple", 3};
std::pair<std::string, int> obj3 = {"Apple", 5};
s.insert{obj1); 
s.insert(obj2); 
s.insert(obj3); 

obj1被添加,因为集合中没有其他可以比较的东西。obj2也被添加,因为它比较不等于obj1。然而。自obj1.second > obj2.second以来,集合中对象的顺序为:

obj1
obj2   

现在,我们来插入obj3.obj3 < obj1的计算结果为true.因此,它会在obj1之前插入。将项目插入集合的逻辑是这样的,obj3永远不会与obj2进行比较。因此,您最终会得到:

obj3
obj1
obj2   

这不是在std::set中比较的工作方式。它旨在提供从最小到大的顺序。使用您的集合,您正在尝试进行 2 种不同类型的比较。

您可以按第一个整数值,其次是字符串值对其进行排序。没关系。

但是,如果一个集合中的 2 个元素比较小,则认为它们相等,如果没有,则它们比另一个元素小。

当你做第一个例子时,这两个元素恰好彼此相邻,所以比较函数将用于它们和你的a.first == b.first情况触发,它们似乎都不比另一个小,所以它们被认为是相等的。

当你进行第二次尝试时,当你插入"Apple", 5你的套装看起来像这样。

Ai 14
Am 14
F 5
Apple 3

Apple, 5在这里比较小然后Am 14,大然后F 5,所以它永远不会与Apple 3进行比较,但它将入两个元素之间,然后它更大更小。由于std::set是按顺序排序的,因此就Compare而言,其他要素已经无关紧要。

问题是第一次比较,这是错误的。删除它,它可以工作。