Использовать n_th элемент в контейнере, но с другим ключом
У меня есть два вектора. Тот, который на самом деле содержит данные (скажем, с плавающей точкой) и тот, который содержит индексы. Я хочу пройти в nth_element
вектор индексов, но я хочу, чтобы сравнение выполнялось вектором, который фактически содержит данные. Я думал о функторе, но я предполагаю, что он предоставляет только оператор (). Я добился этого, сделав вектор данных глобальным, но, конечно, это нежелательно.
std::vector<float> v; // data vector (global)
bool myfunction (int i,int j) { return (v[i]<v[j]); }
int find_median(std::vector<int> &v_i)
{
size_t n = v_i.size() / 2;
nth_element(v_i.begin(), v_i.begin()+n, v_i.end(), myfunction);
return v_i[n];
}
1 ответ
Решение
Вы можете использовать функтор как:
class comp_with_indirection
{
public:
explicit comp_with_indirection(const std::vector<float>& floats) :
floats(floats)
{}
bool operator() (int lhs, int rhs) const { return floats[lhs] < floats[rhs]; }
private:
const std::vector<float>& floats;
};
И тогда вы можете использовать его как:
int find_median(const std::vector<float>& v_f, std::vector<int> &v_i)
{
assert(!v_i.empty());
assert(v_i.size() <= v_f.size());
const size_t n = v_i.size() / 2;
std::nth_element(v_i.begin(), v_i.begin() + n, v_i.end(), comp_with_indirection(v_f));
return v_i[n];
}
Примечание: в C++ 11 вы можете использовать лямбду вместо именованного класса functor.
int find_median(const std::vector<float>& v_f, std::vector<int> &v_i)
{
assert(!v_i.empty());
assert(v_i.size() <= v_f.size());
const size_t n = v_i.size() / 2;
std::nth_element(
v_i.begin(), v_i.begin() + n, v_i.end(),
[&v_f](int lhs, int rhs) {
return v_f[lhs] < v_f[rhs];
});
return v_i[n];
}