使用迭代器仅在某些索引处访问值

ich*_*lus 7 c++ algorithm lambda iterator stl

我很难理解std::accumulate。它可以用于仅对向量的偶数索引求和吗?

int rob(vector<int>& nums) {

    int a = std::accumulate(nums.begin(), nums.end(), 0);

   std::cout <<" a: " <<a; 
   return a;

}
Run Code Online (Sandbox Code Playgroud)

所以如果我有一个 vector y = {1, 2, 3, 4}

我如何更改上面的代码,以便std::accumulate仅对索引[0]和[2]进行迭代。使用它甚至可能std::accumulate吗?

Jer*_*fin 3

你有几个选择。快速且(真正)肮脏的方法是遍历整个集合,并调用一个跟踪当前索引的函数,并忽略奇数索引处的值。它有效,但充其量是丑陋的,更重要的是,它在相当基本的层面上是错误的,迫使应该是累积函数的东西承担迭代的责任。简而言之,这与其说是一个解决方案,不如说是一个问题。

干净的方法是认识到访问集合中的所有其他项目实际上与迭代有关,而不是与特定算法(std::accumulate或任何其他算法)有关。所以我们在这里应该使用一个迭代器来访问我们想要访问的项目。这是一个最小的实现:

#include <vector>
#include <iterator>
#include <iostream>
#include <numeric>

template <class Iterator>
class n_iterator { 
     Iterator i;
     size_t n;
public:
    // We construct this iterator from some other iterator, plus a "step" value
    // to tell us how many items to skip forward when `++` is applied.
    n_iterator(Iterator i, size_t n) : i(i), n(n) {}

    // When you dereference this iterator, it's equivalent to dereferencing
    // the underlying iterator.
    typename std::iterator_traits<Iterator>::value_type operator *() { return *i; }

    // ...but when you increment it, you move ahead N places instead of 1.
    n_iterator &operator++() { std::advance(i, n); return *this; }

    // iterator comparisons just compare the underlying iterators.
    bool operator==(n_iterator const &other) const { return i == other.i; }
    bool operator!=(n_iterator const &other) const { return i != other.i; }
};

int main() { 
    std::vector<int> y { 1, 2, 3, 4};
    auto total = std::accumulate(y.begin(), y.end(), 0);

    std::cout << "total: " << total << "\n";

    auto skip_total = std::accumulate(n_iterator(y.begin(), 2), n_iterator(y.end(), 2), 0);

    std::cout << "Skipped total: " << skip_total << "\n";
}
Run Code Online (Sandbox Code Playgroud)

这个实现似乎足以让 g++ 7.1 编译代码,但对于实际使用,您可能应该实现迭代器的整个接口(例如,至少,它应该真正具有 、value_type等的定义reference

目前,这也仅提供一个前向迭代器,而不管底层迭代器是什么。根据情况(以及底层迭代器的类别),您还可以支持双向和/或随机迭代。