设置存储混乱

Set storage confusion

我已经声明了这样的结构:

struct data{
   vector<string> att;
   string ds;
};

现在一个集合来存储来自多个数据元素的唯一数据

set<data> s;

基于不同的vector<string> attstring ds

如何操作?

在不知道您希望如何比较您的结构的情况下,您可以尝试以下操作:

struct data
{
    vector<string> att;
    string ds;

    friend bool operator < (const data& lhs, const data& rhs)
    {
        if (std::lexicographical_compare(lhs.att.begin(), lhs.att.end(), rhs.att.begin(), rhs.att.end()))
        {
            return true;
        }
        else if (std::lexicographical_compare(rhs.att.begin(), rhs.att.end(), lhs.att.begin(), lhs.att.end()))
        {
            return false;
        }
        else
        {
            return lhs.ds < rhs.ds;
        }
    }
};

我对这个解决方案不满意,因为它执行了两次字典顺序比较,效率很低。希望有人能提出更好的解决方案。

基本思路是,对于每个成员,比较左 < 右。如果为真,则 return 为真,否则比较右 < 左。如果为真,return 为假。否则,继续下一个成员。

注意:您可以阅读更多关于我用来比较事物的技巧 (std::tie) in Implementing comparison operators via 'tuple' and 'tie', a good idea?

std::stringstd::vector 已经定义了 operator<for strings and for vectors。所以我们可以将它们与 std::tie 一起使用来创建一个临时的 std::tuple(它只使用对数据成员的引用,它不会创建任何副本,因此效率很高)以进行比较。


选项 1:提供 operator<

std::set 需要比较它的对象,以便它知道什么是唯一的以及如何对事物进行排序。默认情况下,它将通过使用 operator<(通过 std::less)来执行此操作,因此如果您为 class 提供该运算符,它将使用它。像这样:

struct data{
   vector<string> att;
   string ds;

   operator<(const data& other) {
      // Be sure to #include <tuple> for std::tie
      return std::tie(att, ds) < std::tie(other.att, ds);

      // If you don't want to (or can't) use std::tie, you can do this:
      // return att < other.att || (att == other.att && ds < other.ds);
   }
};
std::set<data> my_set; // Now it works.

选项 2:提供仿函数

这将使用 Compare functor 来比较两个 data 对象(而不是 operator<,因此我们不需要定义它):

struct Compare {
   bool operator()(const data& left, const data& right) const {
      return std::tie(left.att, left.ds) < std::tie(right.att, right.ds);

      // Again, if you don't want to (or can't) use std::tie, you can do this:
      // return left.att < right.att || (left.att == right.att && left.ds < right.ds);
   }
};
std::set<data, Compare> my_set; // Now it works.