【问题标题】:is it possible to using std::pair as key of std::set without any duplicates each element?是否可以使用 std::pair 作为 std::set 的键而每个元素都没有任何重复?
【发布时间】:2021-05-19 23:55:38
【问题描述】:

我正在尝试使用 struct 中的两个整数作为键将 struct 存储在 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::pair 中元素的顺序如何,我都希望std::set 可搜索且不重复。 像这样:

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,并在插入向量之前进行重复检查,如下所示:

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 来实现这些功能?

【问题讨论】:

    标签: c++ c++11 stl


    【解决方案1】:

    用于集合的比较必须满足Compare 命名要求。在这些要求中,还有诱导等价关系的传递性:

    如果equivalent(a,b)equivalent(b,c)equivalent(a,c)

    具体案例:

    • a{1,2}b{1,4}c{3,4}
    • 传递性:如果{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} 被添加到集合中是必需,这是您想要的。

    不,您的目标不能仅通过集合使用的顺序来实现。

    【讨论】:

    • 感谢您的帮助。我认为这有可能,所以我考虑了几个小时,但在阅读了你的答案后,一切都变得清晰了。
    【解决方案2】:

    没有可以使用的严格弱排序,所以不能使用std::set

    但是,您可以使用std::unordered_set,它只需要提供相等性。

    【讨论】:

    • 谢谢,我会检查 unordered_set。
    猜你喜欢
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2022-10-24
    • 2020-08-27
    • 2016-08-14
    相关资源
    最近更新 更多