如何为 std::set<std::p air<int,int 编写自定义比较器>>其中 pair 的第一个元素必须是唯一的

How to write custom comparator for std::set<std::pair<int,int>> where first element of pair must be unique

提问人:TheMemeMachine 提问时间:8/23/2023 最后编辑:Some programmer dudeTheMemeMachine 更新时间:8/23/2023 访问量:41

问:

我在编写严格的弱排序比较器时遇到了麻烦,以便插入对的第一个元素在集合中必须是唯一的,并且对的第二个元素必须按降序排列。std::set<std::pair<int,int>>

这是我的实现:

#include <set>
#include <iostream>

struct Comparator {
    bool operator()(const std::pair<int, int>& lhs, const std::pair<int, int>& rhs) {
        if (lhs.first == rhs.first) {
            return false;
        }
        
        return lhs.second > rhs.second;
    }
};


int main() {
    std::set<std::pair<int, int>, Comparator> s;
    
    s.emplace(1, 1);
    s.emplace(2, 0);
    s.emplace(2, 2);

    for (auto e : s) {
        std::cout << e.first << " " << e.second << std::endl;
    }

    return 0;
};

预期输出:

1 1
2 0

实际产量:

2 2
1 1
2 0

如何强制执行对中第一个元素的唯一性?

C++ 比较器

评论

1赞 Some programmer dude 8/23/2023
每当排序函数不起作用时,可以肯定的是,这是因为它打破了严格的弱排序要求。

答:

1赞 Yakk - Adam Nevraumont 8/23/2023 #1

std::set假设键是根据一组称为严格弱排序的公理进行排序的。在 cppreference 上,它们给出了一套对程序员友好的规则。

它需要:

非反射性:

!( a < a )

及物:

(a < b) and (b < c) means (a < c)

然后,定义为 -- 即,任何一个元素都不小于彼此,因此在 we 下是“等价的”。那么这个等价关系是传递的(显然是反身的):weak_equivalent(a,b)!(a<b) and !(b<a)<

weak_equivalent(a,b) and weak_equivalent(b,c) means weak_equivalent(a,c)

即,描述一堆彼此相等的元素。weak_equivalent

在您的例子中,您似乎希望所有元素 (x,_) 在您的 .<

你希望它按第二个元素排序(向后,但这对我来说并不重要)。

但是(1,5)<(2,3)和(2,3)<(1,1),这意味着(1,5)<(1,1)通过传递要求。

这与您的要求不一致,即 (1,5) 和 (1,1) 是等效的。

所以不能支持这个排序。std::set

一般来说,当你至少不是严格的弱排序时,排序是很困难的,因为你的元素没有一致的顺序。

在你的情况下,你可能应该停止直接使用。std::set

struct my_special_container {
  std::map<int, int> m_s;

  void emplace_if_not_exist( int a, int b ) {
    auto it = m_s.find(b);
    if (it != m_s.end()) {
      m_s[b] = a;
    }
  }
};

现在你只需要编写一个返回元素的迭代器;迭代器会根据您的要求向后执行此操作。map

评论

0赞 TheMemeMachine 8/24/2023
std::multiset 是否支持这样的排序?
0赞 Yakk - Adam Nevraumont 8/24/2023
@TheMemeMachine多集也需要严格的弱排序,所以不需要。multi 的唯一区别是它如何处理等效元素。