[英]c++ std::set equality
I try to use a std::set
in order to have unique elements in my container. 我尝试使用std::set
以便在容器中包含唯一元素。
Since I have 3D objects : 由于我有3D对象:
Class Object3D{
private:
float x;
float y;
float z;
}
Those objects are equal when (Ax==Bx && Ay==By && Az==Bz)
. 当(Ax==Bx && Ay==By && Az==Bz)
时,这些对象是相等的。
In std::set implementation a element A==B if (!(A < B) && !(B>A))
. 在std :: set实现中,元素A==B if (!(A < B) && !(B>A))
。
It's impossible for my comparison... I have tried to overload ==
operator. 我的比较是不可能的......我试图重载==
运算符。
I chose set container for comparing values when I call insert(a)
. 当我调用insert(a)
时,我选择set container来比较值。 I was doing something like that with std::vector v
and his iterator: 我用std::vector v
和他的迭代器做了类似的事情:
if(!(A).inVector()){
v.push_back(A);
}
With 同
bool inVector(){
for(itr = v.begin();itr != v.end();itr++){
if(this->x==(*itr)->x && this->y==(*itr)->y && this->z==(*itr)->z){
return true;
}
}
return false;
}
Checking it for each object (10000-100000) is expensive in complexity. 检查每个对象(10000-100000)的复杂性是昂贵的。
Can someone have an idea ? 有人有想法吗?
You need to implement a strict weak ordering <
for your class. 您需要为您的班级实施严格的弱订单<
。 The easiest way is to use the lexicographic ordering provided by tuple
: 最简单的方法是使用tuple
提供的字典顺序:
#include <tuple>
class Object3D
{
public:
bool operator<(Object3D const & rhs) const
{
return std::tie(x, y, z) < std::tie(rhs.x, rhs.y, rhs.z);
}
// ...
};
@OP: std::set
is a unique, ordered container. @OP: std::set
是一个唯一的,有序的容器。 It requires either an operator<
or a comparator passed explicitly, which implements a strict weak ordering. 它需要一个operator<
或一个显式传递的比较器,它实现了严格的弱排序。
If you don't want to impose an ordering on your elements, don't use an ordered container. 如果您不想对元素进行排序, 请不要使用订购的容器。 You can use std::unordered_set
if you just want to detect uniqueness without imposing an ordering. 如果您只想检测唯一性而不强加std::unordered_set
则可以使用std::unordered_set
。
You need to provide a comparator. 你需要提供一个比较器。 You don't want to implement operator<
, and I agree with that decision. 你不想实现operator<
,我同意这个决定。 You shouldn't provide meaningless functions for your class just to satisfy the constraints of some container. 您不应该为了满足某些容器的约束而为您的类提供无意义的函数。 Thankfully, you don't need operator<
. 谢天谢地,你不需要operator<
。 But you do need a function that has behavior similar to operator<
. 但是你确实需要一个具有类似于operator<
行为的函数。 It doesn't have to mean that one object is considered less than another. 它并不一定意味着一个对象被认为小于另一个对象。 It just needs to provide a strict-weak ordering. 它只需要提供严格弱的排序。 You can give it any name you want. 你可以给它任何你想要的名字。 For example: 例如:
bool Compare_by_x_then_y_then_z(const Object3D& lhs, const Object3D& rhs)
{
if (lhs.getX() != rhs.getX()) return lhs.getX() < rhs.getX();
if (lhs.getY() != rhs.getY()) return lhs.getY() < rhs.getY();
return lhs.getZ() < rhs.getZ();
}
You then provide this function to the constructor of your set: 然后,您将此函数提供给集合的构造函数:
typedef bool(*compT)(const Object3D&, const Object3D&);
std::set<Object3D,compT> objects(Compare_by_x_then_y_then_z);
You have to provide a comparison operator, because std::set
needs it for its implementation. 您必须提供比较运算符,因为std::set
需要它来实现它。
A simple less-than operator would look like this: 一个简单的小于运算符看起来像这样:
bool Object3D::operator<(const Object3D& other) const {
if(x != other.x) return x < other.x;
if(y != other.y) return y < other.y;
return z < other.z;
}
You must declare operator<. 您必须声明operator <。 You can do it like this 你可以这样做
bool operator<(const Object3D& a, const Object3D& b)
{
if (a.x < b.x) return true;
if (b.x < a.x) return false;
if (a.y < b.y) return true;
if (b.y < a.y) return false;
if (a.z < b.z) return true;
if (b.z < a.z) return false;
return false;
}
It is arbitrary, but it doesn't really matter. 它是任意的,但它并不重要。 As long as operator< gives a consistent ordering you'll be OK. 只要运算符<给出一致的顺序,您就可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.