c ++ std :: set equality

时间:2012-10-31 13:06:42

标签: c++ set compare equals

我尝试使用std::set以便在容器中包含唯一元素。

因为我有3D对象:

Class Object3D{  
 private:  
  float x;  
  float y;  
  float z;  
}

(A.x==B.x && A.y==B.y && A.z==B.z)时,这些对象是相同的 在std :: set实现中有一个元素A==B if (!(A < B) && !(B>A)) 我的比较是不可能的......我试图重载==运算符 当我调用insert(a)时,我选择了set container来比较值。 我用std::vector v和他的迭代器做了类似的事情:

if(!(A).inVector()){
 v.push_back(A);
}

使用

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;
}

检查每个对象(10000-100000)的复杂性是很昂贵的 有人有想法吗?

5 个答案:

答案 0 :(得分:7)

您需要为您的班级实施严格的弱排序<。最简单的方法是使用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);
    }

    // ...
};

答案 1 :(得分:4)

@OP:std::set是一个唯一的,有序的容器。它需要显式传递operator<或比较器,这实现了严格的弱排序。

如果您不希望对您的元素强加订购,使用订购的容器。如果您只想检测唯一性而不强制订购,则可以使用std::unordered_set

答案 2 :(得分:2)

你需要提供一个比较器。您不想实施operator<,我同意该决定。您不应该为了满足某些容器的约束而为您的类提供无意义的函数。谢天谢地,您不需要operator<。但是你确实需要一个行为类似于operator<的函数。它不必意味着一个对象被认为小于另一个对象。它只需要提供严格弱的排序。你可以给它任何你想要的名字。例如:

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();
}

然后,您将此函数提供给集合的构造函数:

typedef bool(*compT)(const Object3D&, const Object3D&);
std::set<Object3D,compT> objects(Compare_by_x_then_y_then_z);

答案 3 :(得分:1)

提供比较运算符,因为std::set需要它来实现它。

一个简单的小于运算符看起来像这样:

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;
}

答案 4 :(得分:1)

您必须声明运营商&lt;。你可以这样做

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;
}

这是任意的,但并不重要。只要运营商&lt;给出一致的顺序,你就可以了。