использовать 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];
}

person gsamaras    schedule 05.05.2014    source источник


Ответы (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 вы можете использовать лямбда вместо именованного класса функторов.

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];
}
person Jarod42    schedule 05.05.2014
comment
Отлично! Предполагая, что C ++ 11 доступен, какой из них мы должны предпочесть? Или почти то же самое? - person gsamaras; 05.05.2014
comment
Это то же самое, но именованный функтор можно использовать повторно (например, для полного std::sort) вместо того, чтобы переписывать лямбда X раз. - person Jarod42; 05.05.2014