我尝试使用结构中的两个整数作为键将结构存储在 std::set
中。
我知道可以使用 std::pair
作为 std::set
的键。
struct TYPE{
pair<int, int> nums;
... // some other things
TYPE(){}
TYPE(int first, int second) { nums = make_pair(first, second); }
bool operator<(const TYPE &rhs) const{
return nums < rhs.nums;
}
};
set<TYPE> nums_set;
nums_set.insert(TYPE(1, 2));
nums_set.insert(TYPE(1, 4));
nums_set.insert(TYPE(5, 2));
// size of set : 3, (1,2)(1,4)(5,2)
auto it = nums_set.find(TYPE(1, 2)); // find return (1,2)
但是,我想要可搜索且没有重复的 std::set
,无论 std::pair
中元素的顺序如何。
像这样:
nums_set.insert(TYPE(1, 2));
nums_set.insert(TYPE(1, 4)); // failed. duplicate 1
nums_set.insert(TYPE(4, 2)); // failed. duplicate 2
nums_set.insert(TYPE(4, 1)); // failed. duplicate 1
nums_set.insert(TYPE(3, 4));
// size of set : 2, (1,2)(3,4)
auto it = nums_set.find(TYPE(2, 7)); // find return (1,2).
到目前为止最简单的解决方案是使用 std::vector
代替,并在插入 vector 之前进行重复检查,如下所示:
auto fn = [](const TYPE& e, const TYPE&& t){
return e.nums.first == t.nums.first ||
e.nums.first == t.nums.second ||
e.nums.second == t.nums.first ||
e.nums.second == t.nums.second;
};
vector<TYPE> nums_vec;
nums_vec.push_back(TYPE(1, 2));
if(nums_vec.end() == find_if(nums_vec.begin(), nums_vec.end(),
bind(fn, placeholders::_1, TYPE(1,4))))
{ nums_vec.push_back(TYPE(1,4)); }
但是,我觉得对每个插入都执行此操作以避免重复并不是一个好主意。
所以,我的问题是,是否也可以使用 std::set
来实现这些功能?
最佳答案
用于集合的比较必须满足 Compare命名要求。这些要求之一是导出的等价关系的传递性:
If
equivalent(a,b)
andequivalent(b,c)
thenequivalent(a,c)
.
具体案例:
- 让
a
是{1,2}
,b
是{1,4}
,和c
是{3,4}
. - 传递性: if
{1,2}
相当于{1,4}
和{1,4}
相当于{3,4}
然后{1,2}
相当于{3,4}
.
另一种表达方式 X
相当于 Y
是 X
的存在在你的设置中可以防止 Y
被添加。您想要{1,2}
防止{1,4}
从被添加到集合中。您想要{1,4}
防止{3,4}
从被添加到集合中。为了具有所需的传递性,需要{1,2}
防止{3,4}
避免被添加到集合中,这是您不想要的。
不,您的目标不能仅通过集合使用的顺序来实现。
关于c++ - 是否可以使用 std::pair 作为 std::set 的键而没有任何重复的每个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66236104/