C++ 切片向量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1110523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:49:29  来源:igfitidea点击:

Slicing a vector

c++stl

提问by

I have a std::vector. I want to create iterators representing a slice of that vector. How do I do it? In pseudo C++:

我有一个 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;
}

I would prefer not to have to copy the elements to a new datastructure.

我宁愿不必将元素复制到新的数据结构。

采纳答案by jalf

You'd just use a pair of iterators:

您只需使用一对迭代器:

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;
}

Alternatively, the Boost.Range library should allow you to represent iterator pairs as a single object, but the above is the canonical way to do it.

或者,Boost.Range 库应该允许您将迭代器对表示为单个对象,但以上是执行此操作的规范方法。

回答by Pranjal Mittal

I learnt Python before I learnt C++. I wondered if C++ offered slicing of vectors like slicing in Python lists. Took a couple of minutes to write this function that allows you to slice a vector analogous to the way its done in Python.

在学习 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;
}

Usage:

用法:

vector<int> newvector = slice(vector_variable, start_index, end_index);

The start_index element will be included in the slice, whereas the end_index will not be included.

start_index 元素将包含在切片中,而 end_index 将不包含在内。

Example:

例子:

For a vector v1like {1,3,5,7,9}

对于像 {1,3,5,7,9} 这样的向量v1

slice(v1,2,4) returns {5,7}

slice(v1,2,4) 返回 {5,7}

回答by jdehesa

Taken from here:

取自这里

std::vector<myvector::value_type>(myvector.begin()+start, myvector.begin()+end).swap(myvector);

Usage example:

用法示例:

#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;
}

Outputs:

输出:

bar index 3 contains: 1 2 3
bar index 6 contains: 4 5 6
bar index 9 contains: 7 8 9

回答by kirill_igum

use boost range adapters. they are lazy:

使用升压范围适配器。他们很懒

operator|() is used to add new behaviour lazily and never modifies its left argument.

operator|() 用于懒惰地添加新行为并且从不修改其左参数。

boost::for_each(v|sliced(1,5)|transformed(doSomething));

doSomethingneeds to take range as input. a simple (may be lambda) wrapper would fix that.

doSomething需要将范围作为输入。一个简单的(可能是 lambda)包装器可以解决这个问题。

回答by wilx

As others have said, you can represent the "slice" as pair of iterators. If you are willing to use Boost, you can use the range concept. Then you will have even begin()/end() member functions available and the whole thing looks a lot like a container.

正如其他人所说,您可以将“切片”表示为一对迭代器。如果您愿意使用 Boost,则可以使用范围概念。然后你甚至可以使用 begin()/end() 成员函数,整个事情看起来很像一个容器。

回答by Artur Soler

You can represent those "slices" with a pair of iterators.

您可以用一对迭代器表示这些“切片”。

回答by Zenul_Abidin

You don't need a pair of iterators to slice a vector. Three indexes will do because it allows you to create slices with steps:

您不需要一对迭代器来对向量进行切片。三个索引都可以,因为它允许您使用步骤创建切片:

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;
}

Prints:

印刷:

16
77

In this code, a counter is needed to track the position because not all iterators can do this.

在这段代码中,需要一个计数器来跟踪位置,因为并非所有迭代器都能做到这一点。

回答by Temak

It is possible to use slices with std::valarray. Which is an STL analogue of numpy.arrayin python. It support different vectorized operations like min, max, +,-, *, /, etc. More info here.

可以将切片与std::valarray. 这是numpy.arraypython中的STL模拟。它支持不同的矢量化操作,如 min、max、+、-、*、/ 等。更多信息在这里

std::slice(start, length, stride)allows to select and modify slices of an array without copying (documentation here).

std::slice(start, length, stride)允许在不复制的情况下选择和修改数组的切片(此处为文档)。

The slicing would look like this:

切片看起来像这样:

  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

Or with stride=2:

或与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';