我将点的坐标传递给矢量,并且有一些重复点,所以我想删除其他重复点并保留唯一的点。
例如:
vector<Point2f> points;
points[0]=Point2f(1,1);
points[1]=Point2f(2,3);
points[2]=Point2f(1,1);
points[3]=Point2f(2,3);
points[4]=Point2f(1,1);
points[5]=Point2f(4,1);
我想得到这样的结果:
points[0]=Point2f(1,1);
points[1]=Point2f(2,3);
points[2]=Point2f(4,1);
PS元素的顺序不变。
我试过的内容如下:
#include <opencv2/core/core.hpp>
#include <vector>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
vector<Point2f> pointTemp;
pointTemp[0]=Point2f(1,1);
pointTemp[1]=Point2f(2,3);
pointTemp[2]=Point2f(1,1);
pointTemp[3]=Point2f(2,3);
pointTemp[4]=Point2f(1,1);
pointTemp[5]=Point2f(4,1);
for(vector<Point2f>::iterator it=pointTemp.begin();it!=pointTemp.end();it++)
{
for(vector<Point2f>::iterator it1=it+1;it1!=pointTemp.end();)
{
if(it->x==it1->x&&it->y==it1->y)
{
it1=pointTemp.erase(it1);
}
else
{
it1++;
}
}
}
//cout<<pointTemp.size()<<endl;
return 0;
}
答案 0 :(得分:3)
这是我对它的抨击。它可能要求您将--std=c++11
作为参数传递给g ++。请注意,保留了唯一元素的插入顺序。对于运行时复杂性,它也是O(N)
。
// remove_duplicates: removes all duplicated elements from the vector passed in
void remove_duplicates(std::vector<Point2f>& vec)
{
std::unordered_set<Point2f> pointset; // unordered_set is a hash table implementation
auto itor = vec.begin();
while (itor != vec.end())
{
if (pointset.find(*itor) != pointset.end()) // O(1) lookup time for unordered_set
{
itor = vec.erase(itor); // vec.erase returns the next valid iterator
}
else
{
pointset.insert(*itor);
itor++;
}
}
}
由于使用unordered_set
,上述函数需要先前为Point2f声明哈希函数。你可以随意定义它。我的简单实现如下。
您还可能需要为Point2f定义一个==
运算符以及适当的构造函数来满足vector和unordered_set语义。
完整的代码清单:
#include <vector>
#include <unordered_set>
struct Point2f
{
float x;
float y;
Point2f(float a, float b) : x(a), y(b) {}
Point2f() : x(0), y(0) {}
};
bool operator==(const Point2f& pt1, const Point2f& pt2)
{
return ((pt1.x == pt2.x) && (pt1.y == pt2.y));
}
namespace std
{
template<>
struct hash<Point2f>
{
size_t operator()(Point2f const& pt) const
{
return (size_t)(pt.x*100 + pt.y);
}
};
}
void removedupes(std::vector<Point2f> & vec)
{
std::unordered_set<Point2f> pointset;
auto itor = vec.begin();
while (itor != vec.end())
{
if (pointset.find(*itor) != pointset.end())
{
itor = vec.erase(itor);
}
else
{
pointset.insert(*itor);
itor++;
}
}
}
int main(int argc, char* argv[])
{
std::vector<Point2f> pointTemp;
pointTemp.resize(6);
pointTemp[0]=Point2f(1,1);
pointTemp[1]=Point2f(2,3);
pointTemp[2]=Point2f(1,1);
pointTemp[3]=Point2f(2,3);
pointTemp[4]=Point2f(1,1);
pointTemp[5]=Point2f(4,1);
removedupes(pointTemp);
return 0;
}
答案 1 :(得分:2)
这可以通过首先对点进行排序(使用std :: sort)然后消除重复点(使用std :: unique)来完成。为此,您需要一个函数compare()
#include <algorithm>
// Lexicographic compare, same as for ordering words in a dictionnary:
// test first 'letter of the word' (x coordinate), if same, test
// second 'letter' (y coordinate).
bool lexico_compare(const Point2f& p1, const Point2f& p2) {
if(p1.x < p2.x) { return true; }
if(p1.x > p2.x) { return false; }
return (p1.y < p2.y);
}
bool points_are_equal(const Point2f& p1, const Point2f& p2) {
return ((p1.x == p2.x) && (p1.y == p2.y));
}
void remove_duplicates(std::vector<Point2f>& points) {
// Note: std::unique leaves a 'queue' of duplicated elements
// at the end of the vector, and returns an iterator that indicates
// where to stop (and where to 'erase' the queue)
std::sort(points.begin(), points.end(), lexico_compare);
points.erase(std::unique(points.begin(), points.end(), points_are_equal), points.end());
}
注意1:您可以使用C ++ 0x11 lambdas而不是lexico_compare和points_are_equal两个函数来缩短代码。
注意2:如果你需要保持点的顺序,你可以改为进行间接排序,并跟踪哪些点是重复的。
答案 2 :(得分:0)
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
struct Point2f
{
float x;
float y;
};
int main(int argc, char const *argv[])
{
std::vector<Point2f> points =
{
{1, 1}, {2, 3}, {1, 1}, {2, 3}, {1, 1}, {4, 1}
};
auto print = [&]()
{
for (const auto &point : points)
{
std::cout << "(" << point.x << " " << point.y << ") ";
}
std::cout << std::endl;
};
// first sort
std::sort(points.begin(), points.end(), [](const Point2f & lhs, const Point2f & rhs)
{
return lhs.x < rhs.x && lhs.y < rhs.y;
});
// print
print();
// remove duplicated element
auto it = std::unique(points.begin(), points.end(), [](const Point2f & lhs, const Point2f & rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y;
});
points.resize(std::distance(points.begin(), it));
// print
print();
return 0;
}
答案 3 :(得分:0)
请注意equal function
。如果我们打算剔除similar
个点,则应使用为similar
点赋予相同散列值的散列,以及将approximate-equal
分组为相同的similar points
。就我而言,我使用以下代码:
# include <iostream>
# include <vector>
# include <unordered_set>
# include <utility>
# include <Eigen/Dense>
const std::string red("\033[0;31m");
const std::string green("\033[1;32m");
const std::string yellow("\033[1;33m");
const std::string cyan("\033[0;36m");
const std::string magenta("\033[0;35m");
const std::string reset("\033[0m");
struct ApproxHash
{
std::size_t operator() (Eigen::Vector2d const& pt) const
{
size_t score = (size_t)(pt.x()*100) + (size_t)(pt.y()*10);
std::cerr <<"Point: "<< pt.transpose()<< " has score: "<<score<<std::endl;
return score;
}
};
struct ApproxEqual{
// This is used to guarantee that no duplicates should happen when the hash collision happens.
public:
bool operator()(const Eigen::Vector2d & pt1, const Eigen::Vector2d & pt2) const {
double threshold = 0.00001;
bool xdiff = fabs(pt1.x() - pt2.x())<threshold;
bool ydiff = fabs(pt1.y() - pt2.y())<threshold;
bool result = (fabs(pt1.x() - pt2.x())<threshold) && (fabs(pt1.y() - pt2.y())<threshold);
std::cerr<<cyan<<"Equal is called for: "<< pt1.transpose()<<" and "<<pt2.transpose()<<" which are " << result<<" equal. "<<" xdiff"<< xdiff<<", ydiff"<<ydiff<<reset<<std::endl;
return result;
}
};
void removeDuplicates(std::vector<Eigen::Vector2d>& vec)
{
// If we would like to store values, we should use std::unordered_map.
std::unordered_set<Eigen::Vector2d, ApproxHash, ApproxEqual> pointset;
auto ii = vec.begin();
while (ii != vec.end())
{
std::cerr<<"Processing: "<<ii->transpose()<<std::endl;
if (pointset.find(*ii) != pointset.end()) // O(1) lookup time for unordered_set
{
std::cerr<<red<<"Found duplicate: "<<ii->transpose()<<reset<<std::endl;
vec.erase(ii); // vec.erase returns the next valid iterator
}
else
{
pointset.insert(*ii);
std::cerr<<"Inserted: "<<ii->transpose()<<std::endl;
ii++;
}
}
} // end of removeDuplicates
int main(int argc, char* argv[])
{
std::vector<Eigen::Vector2d> pointTemp;
pointTemp.resize(15);
pointTemp[0]=Eigen::Vector2d(1.0011121213,1);
pointTemp[1]=Eigen::Vector2d(2.0,3.121);
pointTemp[2]=Eigen::Vector2d(4.004,1.0);
pointTemp[3]=Eigen::Vector2d(2.0,3.121);
pointTemp[4]=Eigen::Vector2d(1.001112121,1);
pointTemp[5]=Eigen::Vector2d(4.004,1.0);
pointTemp[6]=Eigen::Vector2d(1.2,1);
pointTemp[7]=Eigen::Vector2d(0.028297902, 0.302034);
pointTemp[8]=Eigen::Vector2d(0.028297901, 0.302034);
pointTemp[9]=Eigen::Vector2d(0.249941, 0.227669);
pointTemp[10]=Eigen::Vector2d(0.249941, 0.227669);
pointTemp[11]=Eigen::Vector2d(0.0206403, 0.304258);
pointTemp[12]=Eigen::Vector2d(0.0206403, 0.304258);
pointTemp[13]=Eigen::Vector2d(0.0206403, 0.304258);
pointTemp[14]=Eigen::Vector2d(0.0282979, 0.302034);
for (auto & point:pointTemp)
{
std::cout<<point.x()<<", "<< point.y()<<std::endl;
}
removeDuplicates(pointTemp);
std::cerr<<green<<"Cleaned vector: "<<reset<<std::endl;
for (auto & point:pointTemp)
{
std::cout<<point.x()<<", "<< point.y()<<std::endl;
}
return 0;
}
我们可以使用g++ -std=c++11 -I /usr/include vectorHash.cpp -o vectorHash
来编译示例。
如果我们使用exact equal
或exact hash
,那么很遗憾我们无法拿起similar points
。