简体   繁体   English

c ++ std :: set equality

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM