Как найти минимальное расстояние с помощью лямбды - PullRequest
0 голосов
/ 04 мая 2020

У меня есть два класса Entity и Ship. Ship наследуется от Entity. Они имеют x и y в качестве атрибутов, которые представляют там положение на 2D-плоскости.

squared_distance функция возвращает расстояние между кораблем и объектом.

class Entity
{
    public:
    int id, x, y;

    Entity(int id, int x, int y) : id(id), x(x), y(y) {}
};

class Ship : public Entity
{
    public:
    int orientation, speed, rum;

    Ship(int id, int x, int y, int ori, int s, int r): 
        Entity(id, x, y)
    {
        orientation = ori;
        speed = s;
        rum = r;
    }
};

int squared_distance(Entity e, Ship s)
{
    return pow((e.x - s.x), 2) + pow((e.y - s.y), 2);
}

Мне нужно найти ближайший объект к кораблю. У меня есть массив Entity с именем entities. Один из способов сделать это: пусть ship - это объект Ship.

index, который передаст индекс ближайшего объекта в ship.

int min_distance = 10000000;
int index;
for (int i = 0; i < entities.size(); ++i)
{
    int curr_distance = squared_distance(entities[i], ship);

    if (curr_distance < min_distance)
    {
        min_distance = curr_distance;
        index = i;
    }
}

How найти ближайший объект с помощью лямбды с std::min_element в библиотеке алгоритмов?

Ответы [ 3 ]

2 голосов
/ 04 мая 2020
int squared_distance(const Entity& e, const Ship& s)
{
    return pow((e.x - s.x), 2) + pow((e.y - s.y), 2);
}

std::min_element(std::begin(entities), std::end(entities), [&ship](const Entity& a, const Entity& b) { return squared_distance(a, ship) < squared_distance(b, ship); });

Обратите внимание, что вам необходимо обновить параметры в вашей декларации squared_distance.

2 голосов
/ 04 мая 2020

Вы можете преобразовать это в std::min_element следующим образом:

auto closer = [&ship](const auto &e1, const auto &e2) {
                return squared_distance(e1, ship) 
                     < squared_distance(e2, ship);
              };

auto it = std::min_element(std::begin(entities), std::end(entities), closer);

Обратите внимание, что этот алгоритм (как и большинство алгоритмов) вернет iterator ближайшему кораблю. Вы можете получить ближайший корабль, разыменовав этот итератор:

auto closest_ship = *it;

Вы также можете получить индекс этого корабля (как у вас есть в вашей версии):

int i = std::distance(std::begin(entities), it);

As @SM в своем ответе указывает, что ваша squared_distance функция должна принимать свои параметры на const&, поскольку вам не нужно делать копии этих объектов, чтобы сравнивать их.

1 голос
/ 04 мая 2020

Что-то вроде

#include <iterator>
#include <algorithm>

//...

auto it = std::min_element( std::begin( entities ), std::end( entities ),
                            [&ship]( const auto &first, const auto &second )
                            {
                                return squared_distance( first, ship ) < squared_distance( second, ship );
                            } );   

Вы можете определить лямбду отдельно, например,

auto less_distance = [&ship]( const auto &first, const auto &second )
{
    return squared_distance( first, ship ) < squared_distance( second, ship );
};   

Тогда вызов алгоритма будет выглядеть как

auto it = std::min_element( std::begin( entities ), std::end( entities ),
                            less_distance );
...