【问题标题】:std::set with std::pair - how to write comparator for elementsstd::set 和 std::pair - 如何为元素编写比较器
【发布时间】:2015-03-09 17:54:05
【问题描述】:

我有一个 std::set 包含 std::pair<T1, T2> 类型的值,并按该对的第一个值排序:

struct Comparator
{
    bool operator() (const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs) const
    {
        return lhs.first < rhs.first;
    }
}

我的定义是std::set&lt;std::pair&lt;T1, T2&gt;, Comparator&gt; s

但是当我尝试插入具有相同第一个值的对时,其中元素插入到之前的集合中(第二个值不同)。该集不插入它。

我希望std::set 仅在该对的第二个值相等(或第一个和第二个相等)的情况下才将元素视为相等。怎么做??

附:我不想使用 boost 库。

【问题讨论】:

  • std::pair 的默认比较如何不适合您的目的?
  • 你所描述的你想要的和你的比较似乎是两件不同的事情。
  • @RetiredNinja,我想要两件事:我想要std::setstd::pair:1) 按配对的第一个值排序。 2)仅当对的第二个值相等时才将值视为相等(这在插入元素时很重要)。我的比较器只满足第一个要求。
  • 一个集合使用相同的比较来排序和确定等价。您的需求与此不符。您需要选择不同的容器。
  • 集合中的相等性由排序决定。如果!(lhs &lt; rhs) &amp;&amp; !(rhs &lt; lhs),则认为两个元素(lhs 和 rhs)相等。 (其中&lt; 是您的比较函数)因此,如果您希望在确定相等性时考虑某个字段,则需要在排序中考虑该字段。

标签: c++ opencv c++11 stl set


【解决方案1】:

但是当我尝试插入具有相同第一个值的对时,其中元素插入到之前的集合中(第二个值不同)。该集合不插入它。

嗯,这就是你所要求的。您的比较器仅查看 first 成员,std::set 不允许重复条目。我猜您可能想先按first 成员排序,如果相等,则按second。因此,将您的比较器更改为以下内容:

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

请注意,这是std::pair would do anyway 的默认运算符&lt;,因此如果您想要这种特定的顺序,只需使用默认值即可。

【讨论】:

  • 又名return lhs &lt; rhs;,如果你只使用std::set&lt;std::pair&lt;T1, T2&gt;&gt;,没有自定义比较器,你会得到这种行为。
  • @BenjaminLindley 我的主要观点是解释比较器的定义如何导致观察到的行为。我不确定这是否真的是 OP 想要的排序,但解决方案应该很容易转移到其他排序。不过,您的观点是有效的。我也会补充的。
  • @5gon12eder,不。我想设置按该对的第一个值排序。集合的元素应该由该对的第二个值唯一。
  • 然后简单地撤销检查:if (lhs.second == rhs.second) return false; else if (lhs.first == rhs.first) return lhs.second &lt; rsh.second; else return lhs.first &lt; rhs.first;.
  • 该比较(在您的最后一条评论中)无效,因为它破坏了传递性。
【解决方案2】:

感谢您的回复。所以,让我们让它更容易完成: 1)排序顺序: lhs.first

我想我想拥有什么很清楚。

我正在使用 CV Open 库编写应用程序。我的集合定义为:

std::set&lt;std::pair&lt;double, cv::Point&gt;, QComparator&gt; s;

QComparator 在哪里:

struct QComparator
{
    bool operator() (const std::pair<double, cv::Point>& lhs, const std::pair<double, cv::Point>& rhs) const
    {
        return lhs.first < rhs.first;
    }
};

附: 我将解释什么是 CV 库中的 cv::Point:

typedef Point_<int> Point2i;
typedef Point2i Point;

怎么做?

【讨论】:

  • 这很奇怪,因为当我尝试在 std::set<:pair int>> 中制作它时,它按预期工作......
【解决方案3】:

这个比较器似乎有效。

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

【讨论】:

    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多