2013-12-20 2 views
0

Я попытался отсортировать точки на основе их координат x и выполнить двоичный поиск по вектору, но я не могу найти точки, которые, как я знаю, они существуют.Каков наилучший способ поиска/поиска точки в векторе точек?

Благодарим за помощь.

struct PointSort { 
    bool operator() (cv::Point pt1, cv::Point pt2) { return (pt1.x < pt2.x);} 
} mySort; 

. 
. 
. 
std::sort (temp.begin(), temp.end(), mySort); 
if (std::binary_search(temp.begin(), temp.end(), somePoint, mySort)){ 
    doSomething(); 
} 
+3

Показать, что вы пробовали. Вы посмотрели на ['std :: find'] (http://en.cppreference.com/w/cpp/algorithm/find)? –

+0

, поэтому у вас есть 2d или 3d точки, и вы хотите найти, есть ли конкретная точка в векторе? или ближайший к вашей точке или что-то подобное? – Raxvan

+0

Да, я тоже пытался найти. но, по-видимому, он не может сравнивать точки! Я добавлю, что я сделал. –

ответ

7

Так что-то вроде:

struct point { int x, y; }; 
std::vector<point> pts { {1,2}, {4,5} }; 
auto comp_x=[](const point& p1, const point& p2) { 
    return p1.x < p2.x; 
}; 
std::sort(begin(pts), end(pts), comp_x); 
//using binary search 
auto it=std::lower_bound(begin(pts), end(pts), some_point, comp_x); 
//it now points to the point 

Нижней границы функции использует бинарный поиск, чтобы найти первый элемент (upper_bound находит последний) и дает итератор этому элементу.

Если вам не нужно его сортировать, я бы просто использовал std::find.

auto it=std::find_if(begin(pts), end(pts), [&](const point& p) { 
     return p.x==some_point.x; 
    } 
); 
+1

Говорите о злоупотреблении 'auto', просто чтобы запутать. –

+3

@JamesKanze, как на земле это злоупотребление авто? Что бы вы делали 'std :: vector :: const_iterator', который вообще не улучшает читаемость, он просто УВЕЛИЧИЛ зависимость от типа контейнера. Почему я должен дважды вводить имя, когда компилятор знает, о чем я говорю? – 111111

+1

Также смотрите: http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/ – 111111

0

Если вы просто хотите, чтобы найти Point, который соответствует одному вы подачи:

std::vector<Point> points; 
// points is filled somewhere 
Point p { 1, 2 }; 
std::vector<Point>::iterator it = std::find(points.begin(), points.end(), p); 

Если вы хотите настроить сравнение, вы можете использовать std::find_if:

Point pt { 1, 2 }; 
std::vector<Point>::iterator it = std::find_if(points.begin(), points.end(), [&](const Point& p) 
{ 
    return pt.x == p.x; 
}); 

И, ради Бога, игнорировать вздор «AAA» ...

Боковое примечание: ваш вектор не нужно сортировать, чтобы использовать std::find (хотя он ускорит его, если он есть). И если вы можете использовать стандарт C++ 11, вам не нужно, чтобы создать функтор:

std::sort(temp.begin(), temp.end(), [](const Point& p1, const Point& p2) 
{ 
    return p1.x < p2.x; 
}); 

Кроме того, если элементы вашего Point класса чисел с плавающей точкой, вы не хотите использовать прямое равенство для сравнений. Вместо этого, нарвать небольшое количество в качестве минимальной приемлемой точности (эпсилон), и сравнить разницу между 2 значения к нему:

float x = SOME_VALUE; 
float y = SOME_OTHER_VALUE; 
float EPSILON = 0.000000001; 
bool are_equal = std::abs(x - y) < EPSILON; 
+1

Нет, вы не должны игнорировать «нонсенс» AAA ... Особенно для этих итераторов «авто» идеально. – leemes

+0

@ Zac да, потому что код (второй листинг) ТАК гораздо читабельнее? (Риторический), и я полагаю, вы гораздо лучше владели этим вопросом, чем Саттер. – 111111

+0

@leemes Замена 'std :: vector :: iterator it = ...' с 'auto it = ...' - отличный способ получить smackdown в обзоре кода. Обычно я вижу две причины: 1) более короткая типизация и 2) она позволяет вам изменять контейнер без необходимости обновления определения типа. В 1), это просто лень и как таковая не имеет значения. В 2), если вы меняете тип контейнера, вероятно, будет много других проблем, о которых вам придется позаботиться, поэтому обновление ваших объявлений итераторов является наименьшим из ваших забот. –

Смежные вопросы