在std :: map中重复删除

时间:2017-09-04 11:51:37

标签: c++ duplicates containers stdmap

与下面的链接类似,

https://stackoverflow.com/a/30424281/1442787

我的班级Point包含成员变量double x,y,z

我在课程中重载operator <以将值插入std::map

bool Point::operator<(const Point &p)const{
    return (   x < p.x
            || (   x == p.x
                && (   y < p.y
                    || (   y == p.y
                        && z < p.z))));
}

我已将Point类定义为键,将std::pair定义为值

typedef std::pair<int,int> mypair;
typedef std::map<Point, mypair> mymap;

std::map不允许插入重复的密钥。

但是,在我的代码中,插入键/值对时,重复键也会被插入,如下所示

map:0.436612,16.527741,0.000000,22,2
map:0.454781,17.427262,15.264347,74,12
map:0.454781,17.427262,15.264347,27,11
map:0.608370,17.373443,20.124160,21,13
map:0.608370,17.373443,20.124160,69,11

重复插入的原因是什么?

2 个答案:

答案 0 :(得分:0)

你的问题是浮点值很少比较相等,特别是如果它们是计算的结果(但是在更平凡的情况下它们可能是不相等的,因为它们在内存中存储的大小不同于寄存器中的大小)。

首先,您应该避免使用浮点作为键。

如果你真的想要这样做,那么你应该有一些特定领域的比较运算符。您可以使用epsilon-tolerance(如果abs(x - y) < e,则两个浮点数相等,其中e是一个小值),或者您可以使用与数字一致的容差值(基本上,产生类似“两个数字等于一定数量的有效数字“)。单元测试库(例如the Boost Test library)使用这些类型的比较。对于点,您可以使用基于距离的相等:两个点相等,如果它们彼此更接近而不是某个值。

以前我提到了等式谓词。你可以像这样进行比较:

bool Point::operator==(const point &p)const{
    // Using Manhattan distance here.
    return (x - p.x) + (y - p.y) + (z - p.z) < 0.0001;
}

bool Point::operator<(const Point &p)const{
    return p != *this && (   x < p.x
            || (   x == p.x
                && (   y < p.y
                    || (   y == p.y
                        && z < p.z))));
}

答案 1 :(得分:-1)

我建议您使用std::multimap,因为它可以存储重复值...

如果你想确保你要添加的给定点不在现有点的小容差范围内,那么我会检查x坐标在公差范围内的任何点。

因此,要找到这一点,您可以创建一个点:

 Point search { x - tolerance, -Inf, -Inf };

然后使用lower_bound作为起点并测试任何后续点,直到其x坐标大于x + tolerance