在包含自定义类型的集合中查找

Find in a set containing self defined type

本文关键字:集合 查找 类型 包含 自定义      更新时间:2023-10-16

我有一个存储自定义数据的集合,我想按键值搜索它。

下面是一个简单的例子:

struct Data {
  Data(int x, int y):x(x), y(y){}
  int x;
  int y;
};
struct Compare {
  bool operator() (const Data& lhs, const Data& rhs) {
    return lhs.x < rhs.x;
  }
};
int main()
{
  set<Data, Compare> s;
  s.insert(Data(2, 77));
  s.insert(Data(3, 15));
  s.insert(Data(1, 36));
  for (auto i:s)
    cout<<i.x<<" "<<i.y<<endl;
  auto i = s.find(3);  // <-- Not working
  auto i = s.find(Node(3, 0));
  if (i != s.end())
    cout<<"found"<<endl;
  else
    cout<<"not found"<<endl;
}

这个集合只按x排序,但是我必须创建一个临时对象来搜索这个集合:s.find(Node(3, 0))

可以只按键搜索吗?即s.find(3) ?

在c++14中,您可以使用is_transparent:

查找一个键值与值x相等的元素。此重载仅在重载解析中参与qualified-id Compare::is_transparent是有效的,并且表示一个类型。它允许在不构造Key实例的情况下调用此函数

struct Compare {
  using is_transparent = std::true_type;
  bool operator() (const Data& lhs, const Data& rhs) const {
    return lhs.x < rhs.x;
  }
  bool operator() (const Data& lhs, const int & rhsx) const {
    return lhs.x < rhsx;
  }
  bool operator() (const int & lhsx, const Data& rhs) const {
    return lhsx < rhs.x;
  }
};

你为什么不写这样的东西呢?

Data myFind(const set<Data, Compare>& s, int x) {
   auto it = s.find(Node(x, 0));
   return *it;
}

您的代码有错误。std::set是一个唯一的容器,这意味着它不希望包含两个彼此相等的值。然而,通过给这个集合一个只使用x的比较函数,你已经使得具有相同x分量的两个值被这个集合认为是相等的,不管它们的y是否匹配。这将防止您为x插入多个值(这可能是您想要的…如果是,忽略这一部分。)更好的比较方法是通过查看y来打破x中的联系(这被称为"字典式"比较:

struct Compare {
  bool operator() (const Data& lhs, const Data& rhs) {
    if(lhs.x != rhs.x) return lhs.x < rhs.x;
    return lhs.y < rhs.y;
  }
};

现在,对于通过与键不具有相同类型的东西进行搜索。这在c++ 14中成为可能,因为关联容器的搜索函数中出现了一些新的重载。有关更多信息,请参阅关于unique_ptrs集合的原始指针查找的第一个答案。基本上,您为比较器提供了一个"is_transparent"成员来标记它,并使它能够将Data与您打算搜索的任何类型进行比较。