我有一个std :: vector。我想创建表示该向量切片的迭代器。我该怎么做?在伪C ++中:
class InterestingType;
void doSomething(slice& s) {
for (slice::iterator i = s.begin(); i != s.end(); ++i) {
std::cout << *i << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
slice slice1 = slice(v, 1, 5);
slice slice2 = slice(v, 2, 4);
doSomething(slice1);
doSomething(slice2);
return 0;
}
我不希望将元素复制到新的数据结构中。
答案 0 :(得分:28)
您只需使用一对迭代器:
typedef std::vector<int>::iterator vec_iter;
void doSomething(vec_iter first, vec_iter last) {
for (vec_iter cur = first; cur != last; ++cur) {
std::cout << *cur << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
doSomething(v.begin() + 1, v.begin() + 5);
doSomething(v.begin() + 2, v.begin() + 4);
return 0;
}
或者,Boost.Range库应该允许您将迭代器对表示为单个对象,但以上是执行它的规范方法。
答案 1 :(得分:9)
我在学习C ++之前学过Python。我想知道C ++是否提供了像Python列表中的切片一样的切片。花了几分钟来编写这个函数,它允许你切割一个类似于它在Python中完成的方式的向量。
vector<int> slice(const vector<int>& v, int start=0, int end=-1) {
int oldlen = v.size();
int newlen;
if (end == -1 or end >= oldlen){
newlen = oldlen-start;
} else {
newlen = end-start;
}
vector<int> nv(newlen);
for (int i=0; i<newlen; i++) {
nv[i] = v[start+i];
}
return nv;
}
vector<int> newvector = slice(vector_variable, start_index, end_index);
start_index元素将包含在切片中,而end_index将不包含在内。
对于矢量 v1 ,如{1,3,5,7,9}
slice(v1,2,4)返回{5,7}
答案 2 :(得分:5)
取自here:
std::vector<myvector::value_type>(myvector.begin()+start, myvector.begin()+end).swap(myvector);
用法示例:
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> indexes{3, 6, 9};
for( auto index : indexes )
{
int slice = 3;
std::vector<int> bar{1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int>( bar.begin() + index - slice, bar.begin() + index ).swap(bar);
std::cout << "bar index " << index << " contains:";
for (unsigned i=0; i<bar.size(); i++)
std::cout << ' ' << bar[i];
std::cout << '\n';
}
return 0;
}
输出:
bar index 3 contains: 1 2 3
bar index 6 contains: 4 5 6
bar index 9 contains: 7 8 9
答案 3 :(得分:2)
您可以使用一对迭代器来表示这些“切片”。
答案 4 :(得分:2)
正如其他人所说,你可以将“切片”表示为一对迭代器。如果您愿意使用Boost,则可以使用范围概念。那么你甚至可以使用begin()/ end()成员函数,整个看起来就像一个容器。
答案 5 :(得分:2)
使用增压范围适配器。他们是lazy:
运算符|()用于懒惰地添加新行为,永远不会修改它 左参数。
boost::for_each(v|sliced(1,5)|transformed(doSomething));
doSomething
需要将范围作为输入。一个简单的(可能是lambda)包装器可以解决这个问题。
答案 6 :(得分:0)
您不需要一对迭代器即可分割向量。可以使用三个索引,因为它允许您使用以下步骤创建切片:
static const int arr[] = {16,2,77,29,42};
vector<int> v (arr, arr + sizeof(arr) / sizeof(arr[0]) );
vector<int>::iterator i;
const int step = 2;
const int first = 0;
const int last = v.size()-1;
int counter=first;
for (i = v.begin()+first; counter<last; i+=step, counter+=step) {
// Do something with *i
cout << *i << endl;
}
打印:
16
77
在此代码中,需要计数器来跟踪位置,因为并非所有迭代器都可以执行此操作。
答案 7 :(得分:0)
可以将切片与std::valarray
一起使用。这是python中numpy.array
的STL类似物。它支持不同的矢量化操作,例如min,max,+,-,*,/等。
更多信息here。
std::slice(start, length, stride)
允许选择和修改数组的切片而无需复制(文档here)。
切片看起来像这样:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | | | |
std::slice myslice=std::slice(1,5,1); // v v v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 20 30 40 50 6 7 8
或使用stride=2
:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | |
std::slice myslice=std::slice(1,3,2); // v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 2 30 4 50 6 7 8
// | | |
foo[std::slice (0,3,3)] = 99; // v v v
// 99 10 2 99 4 50 99 7 8
std::cout << "foo:";
for (std::size_t n=0; n<foo.size(); n++)
std::cout << ' ' << foo[n];
std::cout << '\n';