仅在使用迭代器的某些索引上生成值

Acessing Values only at certain indexes using iterators

本文关键字:索引 迭代器      更新时间:2023-10-16

我很难理解std::accumulate。它可以用来将向量中偶数索引的值相加吗?

int rob(vector<int>& nums) {
int a = std::accumulate(nums.begin(), nums.end(), 0);
std::cout <<" a: " <<a; 
return a;
}

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

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

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

干净的方法是意识到访问集合中的所有其他项目实际上是关于迭代的,而不是关于特定的算法(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";
}

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

目前,这也只提供一个前向迭代器,而不考虑底层迭代器。根据情况(和底层迭代器的类别(,您还可以支持双向和/或随机迭代。

你来了

int rob( const vector<int>& nums) {
int i = 0;
int a = std::accumulate(nums.begin(), nums.end(), 0,
[&i]( const auto &acc, const auto &value )
{
return ( i ^= 1 ) ? acc + value : acc;
} );
std::cout <<" a: " <<a; 
return a;
}

这是一个演示程序

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums )
{
int i = 0;
int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
[&i]( const auto &acc, const auto &value )
{
return ( i ^= 1 ) ? acc + value : acc;
} );
return a;
}
int main() 
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << rob( v ) << 'n';
return 0;
}

它的输出是

20

您可以向函数再添加一个参数,您可以选择是求和偶数还是奇数。例如

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums, bool odds = false )
{
int i = odds;
int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
[&i]( const auto &acc, const auto &value )
{
return ( i ^= 1 ) ? acc + value : acc;
} );
return a;
}
int main() 
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << rob( v ) << 'n';
std::cout << rob( v, true ) << 'n';
return 0;
}

程序输出为

20
25

在这种情况下,您可以删除变量 i 的声明。例如

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int rob( const std::vector<int> &nums, bool odds = false )
{
int a = std::accumulate( std::begin( nums ), std::end( nums ), 0,
[&odds]( const auto &acc, const auto &value )
{
return ( odds = !odds ) ? acc + value : acc;
} );
return a;
}
int main() 
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << rob( v ) << 'n';
std::cout << rob( v, true ) << 'n';
return 0;
}