Название: Поиск лучшего элемента через stl/boost алгоритм Отправлено: kamre от Июнь 29, 2018, 08:48 Задача простая и довольно типичная:
- имеется последовательность элементов (может быть контейнер, пара итераторов, ...) - есть нетривиальный алгоритм для оценки элементов, результат представляется в виде значения типа double, - нужно найти элемент (его индекс/итератор) с максимальным значением оценки. По сути нужно применить к каждому элементу алгоритм оценки и выбрать тот, у которого оценка максимальная. Алгоритм для оценки сложный и вызывать его несколько раз для одного и того же элемента неэффективно. Как можно эту простую задачу решить через алгоритмы в stl/boost чтобы не писать каждый раз вручную цикл наподобие такого: Код: #include <vector> Алгоритм std::max_element не подходит сразу, т.к. требует предикат для сравнения и будет несколько раз вызывать функцию оценки для одного и того же элемента. Попробовал также boost::range, там есть boost::adaptors::transformed, но в него не получается передавать lambda, которая захватывает контекст. Оборачивать такую lambda в std::function - опять же потеря производительности, насколько я понимаю. Так чем можно заменить простой цикл с поиском лучшего элемента? Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: Пантер от Июнь 29, 2018, 09:00 > Алгоритм std::max_element не подходит сразу, т.к. требует предикат для сравнения и будет несколько раз вызывать функцию оценки для одного и того же элемента.
Что тебе мешает закешировать в предикате? Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: kamre от Июнь 29, 2018, 09:53 Что тебе мешает закешировать в предикате? Что именно закешировать? Одно значение только? Все равно придется сравнивать с двумя аргументами предиката, это лишняя работа.Меня бы устроил вариант через boost::range типа такого: Код: auto iter = boost::max_element(points | boost::adaptors::transformed(cost)); Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: qate от Июнь 29, 2018, 11:01 Что тебе мешает закешировать в предикате? Что именно закешировать? Одно значение только? Все равно придется сравнивать с двумя аргументами предиката, это лишняя работа.наверно имелось ввиду закэшировать в мапе QHash<Point, double> произведенные расчеты, тогда для того же Point расчет уже выполнен Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: m_ax от Июнь 29, 2018, 11:58 Да тут, наверное, проще свой qmax_element написать:
Код
Цитировать Меня бы устроил вариант через boost::range А в чём там выйгрышь? Он ведь тоже использует std::max_element в конечном счёте..https://www.boost.org/doc/libs/1_56_0/boost/range/algorithm/max_element.hpp (https://www.boost.org/doc/libs/1_56_0/boost/range/algorithm/max_element.hpp) Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: kamre от Июнь 29, 2018, 12:31 Да тут, наверное, проще свой qmax_element написать: Вот у меня такое же мнение сложилось, что придется самому написать. Странно, что такая простая задача комбинацией готовых алгоритмов не решается.А в чём там выйгрышь? Он ведь тоже использует std::max_element в конечном счёте.. Да, boost::range не подходит в таком случае.Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: m_ax от Июнь 29, 2018, 12:35 Цитировать Странно, что такая простая задача комбинацией готовых алгоритмов не решается. Не, в принципе, решается через тот же std::max_element, но это на любителя:Код
Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: Igors от Июнь 29, 2018, 16:21 Странно, что такая простая задача комбинацией готовых алгоритмов не решается. Я этому давно не удивляюсь. Простецкий for часто оказывается лучшим решением. Хороших, полезных вещей в std::algorithm мало, основная масса так - написать вумную соплю чтобы было на 1-2 строки меньше.Название: Re: Поиск лучшего элемента через stl/boost алгоритм Отправлено: ViTech от Июнь 30, 2018, 13:17 Меня бы устроил вариант через boost::range типа такого: Код: auto iter = boost::max_element(points | boost::adaptors::transformed(cost)); С лямбдой работает Range-v3 (https://ericniebler.github.io/range-v3/): Код
Но во время работы ranges::max_element могут повторно вычисляться cost (для текущей максимальной точки). Да тут, наверное, проще свой qmax_element написать: Вот у меня такое же мнение сложилось, что придется самому написать. Странно, что такая простая задача комбинацией готовых алгоритмов не решается.Задача может не такая уж и простая. Стандартные алгоритмы не знают, что можно кэшировать, а что нужно вычислять каждый раз. Может в cost рандом какой присутствует, или зависимость от времени. Алгоритму нужно об этом как-то сообщать. И в этом случае действительно проще свой алгоритм написать. |