STL:将函数应用于没有额外容器的adjacent_difference的结果

时间:2018-02-22 13:01:46

标签: c++ stl

在std :: adjacent_difference结果上应用某些操作(例如找到min)的最佳方法是什么,而不创建额外的容器?

编辑:手动循环是显而易见的方式,但STL不够。

一种方法是实现output_iterator但看起来有点沉重:

template<typename T>
class find_min_oit {
    T min = std::numeric_limits<T>::max();
public:

    using iterator_category = std::output_iterator_tag;

    find_min_oit& operator++() {
        return *this;
    }

    find_min_oit& operator++(int) {
        return *this;
    }

    find_min_oit& operator*() {
        return *this;
    }

    find_min_oit& operator=(T const& value){
        if (value < min){
            min = value;
        }

        return *this;
    }

    T result() const {
        return min;
    }

};

void find_min(){
    vector<int> arr{1,2,3,6,15};

    auto res = std::adjacent_difference(arr.begin(), arr.end(), find_min_oit<int>());
    std::cout << res.result() << std::endl;
}

5 个答案:

答案 0 :(得分:2)

您可以使用boost::function_output_iterator来定义迭代器。

void find_min(){
    vector<int> arr{1,2,3,6,15};
    int result = std::numeric_limits<int>::max();

    auto oit = boost::make_function_output_iterator([&result](int value) { result = std::min(value, result); });
    std::adjacent_difference(arr.begin(), arr.end(), oit);
    std::cout << result << std::endl;
}

答案 1 :(得分:1)

只是去手动循环,不幸的是,标准算法不是在没有成本的情况下组合的......您可以查看range v3库,它允许您以更低成本的方式组合算法

template <class InputIt>
auto find_adjacent_min_v3(InputIt first, InputIt last) {
    auto min = std::numeric_limits<typename InputIt::value_type>::max();
    for (auto it = first++; first < last; ++first, ++it) {
        if (*it - *first < min) {
            min = *it - *first;
        }
    }
    return min;
}

为了练习,这是一个使用标准std::accumulate和自定义“累加器”的版本:

template <class InputIt>
auto find_adjacent_min(InputIt first, InputIt last) {
    auto max = std::numeric_limits<typename InputIt::value_type>::max();
    return std::accumulate(
        std::next(first), last, std::make_pair(*first, max),
        [](auto p, auto x) { 
            auto diff = (x - p.first) < p.second ?
                x - p.first : p.second;
            return std::make_pair(x, diff);
    }).second;
}

答案 2 :(得分:1)

您可以使用std::adjacent_find

int find_min(){
    vector<int> arr{1,2,3,6,15};

    int min = std::numeric_limits<int>::max();
    std::adjacent_find(arr.begin(), arr.end(), [&](auto a, auto b){
        if ((a - b) < min)
            min = a-b;
        return false;
    });
    return min;
}

答案 3 :(得分:0)

您有80%的时间来回答您自己的问题:只需添加另一个模板参数typename On_Assignment,将find_min_oit重命名为更通用且来自On_Assignment的内容,以便您可以注入数据成员,然后允许operator=提供On_Assignment。然后,您只需要几行来编写带有operator=的struct,以便在处理adjacent_difference将提供的值时产生变化。或者,将自定义行为传递给构造函数并将其保存在std::function中以供operator=使用:然后您可以传入lambda。

答案 4 :(得分:0)

如果 可以接受输入数据的更改,您可以尝试这样的事情:

std::min_element(x.begin() + 1, std::adjacent_difference(x.begin(), x.end(), x.begin());

CPP reference明确指出允许输入和输出开始相等。