如何实现"InterpolatedVector"?
How to implement a "InterpolatedVector"?
我有一个 std::vector<double>
,我需要插入它的值。例如,只有 1 个中间值并给定一个填充有
的向量
1 / 2 / 3 / 4
我想访问以下值
1 / 1.5 / 2 / 2.5 / 3 / 3.5 / 4
当然我不必存储这个中间值(简单的线性插值,我不必经常读取它们),所以我写了这个简单的class:
typedef std::vector<double> DVector;
class InterpolatedVector {
public:
InterpolatedVector(const DVector& v,int steps) : v(v),steps(steps){}
double at(int i){
int j = i%steps;
int k = (int)i/steps;
if (i==0){return v[0];}
else if (i==v.size()*steps){return v.back();}
else {return ((steps-j)*v[k] + j*v[k+1])/steps;}
}
int size(){return steps*(v.size()-1) + 1;}
private:
DVector v;
int steps;
};
它工作正常,我(几乎)得到了我想要的。但是,这个 "container" 我不能与 std::algorithms 一起使用,而且我没有它的迭代器。 (当然,我不能写中间值,但至少在阅读时,我想使用算法。)我应该指出,我对迭代器之类的东西仍然缺乏一点理解。
我应该如何实现这个"InterpolatedVector",这样我就可以做像
这样的事情
std::accumulate(/* passing Interpolated iterators? */ );
?
如果您想将它与算法一起使用,请用中间值填充一个向量。这样会简单很多。
鉴于您已经拥有处理索引本身的代码,将其包装为迭代器非常容易。如果你能原谅我,我也会让它更通用一些。
#include <vector>
#include <iterator>
template <class T>
class InterpolatedVector {
typedef std::vector<T> DVector;
public:
InterpolatedVector(const DVector& v,int steps) : v(v),steps(steps){}
T at(int i){
int j = i%steps;
int k = (int)i/steps;
if (i==0){return v[0];}
else if (i==v.size()*steps){return v.back();}
else {return ((steps-j)*v[k] + j*v[k+1])/steps;}
}
int size(){return steps*(v.size()-1) + 1;}
class iterator : public std::iterator < std::random_access_iterator_tag, T > {
InterpolatedVector *vec;
int index;
public:
iterator(InterpolatedVector &d, int index) : vec(&d), index(index) {}
iterator &operator++() { ++index; return *this; }
iterator operator++(int) { iterator tmp{ *vec, index }; ++index; return tmp; }
iterator operator+(int off) { return iterator(*vec, index + off); }
iterator operator-(int off) { return iterator(*vec, index - off); }
value_type operator*() { return (*vec).at(index); }
bool operator!=(iterator const &other) { return index != other.index; }
bool operator<(iterator const &other) { return index < other.index; }
};
iterator begin() { return iterator(*this, 0); }
iterator end() { return iterator(*this, size()); }
private:
DVector v;
int steps;
};
...以及一些用于测试的演示代码:
#include <iostream>
int main() {
std::vector<double> d{ 1, 2, 3, 4 };
InterpolatedVector<double> id(d, 2);
std::copy(id.begin(), id.end(), std::ostream_iterator<double>(std::cout, "\t"));
std::cout << "\n";
std::vector<int> i{ 0, 5 };
InterpolatedVector<int> ii(i, 5);
std::copy(ii.begin(), ii.end(), std::ostream_iterator<int>(std::cout, "\t"));
}
输出:
1 1.5 2 2.5 3 3.5 4
0 1 2 3 4 5
当然,有些算法仍然不能用这种 "collection" 做很多事情。尝试将插值集合提供给 std::sort
没有多大意义(您显然需要对底层容器进行排序)。只要算法只需要读取数据就可以了。
我有一个 std::vector<double>
,我需要插入它的值。例如,只有 1 个中间值并给定一个填充有
1 / 2 / 3 / 4
我想访问以下值
1 / 1.5 / 2 / 2.5 / 3 / 3.5 / 4
当然我不必存储这个中间值(简单的线性插值,我不必经常读取它们),所以我写了这个简单的class:
typedef std::vector<double> DVector;
class InterpolatedVector {
public:
InterpolatedVector(const DVector& v,int steps) : v(v),steps(steps){}
double at(int i){
int j = i%steps;
int k = (int)i/steps;
if (i==0){return v[0];}
else if (i==v.size()*steps){return v.back();}
else {return ((steps-j)*v[k] + j*v[k+1])/steps;}
}
int size(){return steps*(v.size()-1) + 1;}
private:
DVector v;
int steps;
};
它工作正常,我(几乎)得到了我想要的。但是,这个 "container" 我不能与 std::algorithms 一起使用,而且我没有它的迭代器。 (当然,我不能写中间值,但至少在阅读时,我想使用算法。)我应该指出,我对迭代器之类的东西仍然缺乏一点理解。
我应该如何实现这个"InterpolatedVector",这样我就可以做像
这样的事情std::accumulate(/* passing Interpolated iterators? */ );
?
如果您想将它与算法一起使用,请用中间值填充一个向量。这样会简单很多。
鉴于您已经拥有处理索引本身的代码,将其包装为迭代器非常容易。如果你能原谅我,我也会让它更通用一些。
#include <vector>
#include <iterator>
template <class T>
class InterpolatedVector {
typedef std::vector<T> DVector;
public:
InterpolatedVector(const DVector& v,int steps) : v(v),steps(steps){}
T at(int i){
int j = i%steps;
int k = (int)i/steps;
if (i==0){return v[0];}
else if (i==v.size()*steps){return v.back();}
else {return ((steps-j)*v[k] + j*v[k+1])/steps;}
}
int size(){return steps*(v.size()-1) + 1;}
class iterator : public std::iterator < std::random_access_iterator_tag, T > {
InterpolatedVector *vec;
int index;
public:
iterator(InterpolatedVector &d, int index) : vec(&d), index(index) {}
iterator &operator++() { ++index; return *this; }
iterator operator++(int) { iterator tmp{ *vec, index }; ++index; return tmp; }
iterator operator+(int off) { return iterator(*vec, index + off); }
iterator operator-(int off) { return iterator(*vec, index - off); }
value_type operator*() { return (*vec).at(index); }
bool operator!=(iterator const &other) { return index != other.index; }
bool operator<(iterator const &other) { return index < other.index; }
};
iterator begin() { return iterator(*this, 0); }
iterator end() { return iterator(*this, size()); }
private:
DVector v;
int steps;
};
...以及一些用于测试的演示代码:
#include <iostream>
int main() {
std::vector<double> d{ 1, 2, 3, 4 };
InterpolatedVector<double> id(d, 2);
std::copy(id.begin(), id.end(), std::ostream_iterator<double>(std::cout, "\t"));
std::cout << "\n";
std::vector<int> i{ 0, 5 };
InterpolatedVector<int> ii(i, 5);
std::copy(ii.begin(), ii.end(), std::ostream_iterator<int>(std::cout, "\t"));
}
输出:
1 1.5 2 2.5 3 3.5 4
0 1 2 3 4 5
当然,有些算法仍然不能用这种 "collection" 做很多事情。尝试将插值集合提供给 std::sort
没有多大意义(您显然需要对底层容器进行排序)。只要算法只需要读取数据就可以了。