关联容器所需的比较器
Comparator needed for an associative container
我需要一个 std::set<std::pair<std::string, int>, Compare>
根据它们的 int 值(以相反的顺序)比较两对,如果它们的 int 值相同则根据它们的字符串值(以相同的顺序), 但如果它们的字符串相等,则这两对被视为相等 (无论它们的 int 值如何)。所以我想出的 Compare
class 是:
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
class 中的逻辑错误是什么?它应该是什么?我考虑过使用 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 种不同类型的比较。
您可以先按整数值,再按字符串值排序。没问题。
但是如果 none 如果一个集合中的 2 个元素比另一个元素更小,则它们被认为是相等的。
当您执行第一个示例时,这两个元素恰好彼此相邻,因此将对它们使用比较函数,并且您的 a.first == b.first
个案例触发器和 none 个似乎比另一个小,所以它们被认为是相等的。
当你第二次尝试时,当你插入时 "Apple", 5
你的设置看起来像这样。
Ai 14
Am 14
F 5
Apple 3
Apple, 5
将在这里比较小于 Am 14
和大于 F 5
所以它永远不会与 Apple 3
进行比较,但它会被插入到两个元素然后它变大变小。由于 std::set
预计已按顺序排序,因此就 Compare
而言,超出的元素无关紧要。
我需要一个 std::set<std::pair<std::string, int>, Compare>
根据它们的 int 值(以相反的顺序)比较两对,如果它们的 int 值相同则根据它们的字符串值(以相同的顺序), 但如果它们的字符串相等,则这两对被视为相等 (无论它们的 int 值如何)。所以我想出的 Compare
class 是:
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
class 中的逻辑错误是什么?它应该是什么?我考虑过使用 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 种不同类型的比较。
您可以先按整数值,再按字符串值排序。没问题。
但是如果 none 如果一个集合中的 2 个元素比另一个元素更小,则它们被认为是相等的。
当您执行第一个示例时,这两个元素恰好彼此相邻,因此将对它们使用比较函数,并且您的 a.first == b.first
个案例触发器和 none 个似乎比另一个小,所以它们被认为是相等的。
当你第二次尝试时,当你插入时 "Apple", 5
你的设置看起来像这样。
Ai 14
Am 14
F 5
Apple 3
Apple, 5
将在这里比较小于 Am 14
和大于 F 5
所以它永远不会与 Apple 3
进行比较,但它会被插入到两个元素然后它变大变小。由于 std::set
预计已按顺序排序,因此就 Compare
而言,超出的元素无关紧要。