Slicing a vector

后端 未结 8 1943
伪装坚强ぢ
伪装坚强ぢ 2020-12-14 01:12

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

class InterestingType;

void doSomethi         


        
相关标签:
8条回答
  • 2020-12-14 01:44

    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.

    0 讨论(0)
  • 2020-12-14 01:45

    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.

    0 讨论(0)
  • 2020-12-14 01:45

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

    0 讨论(0)
  • 2020-12-14 01:52

    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.

    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.

    Example:

    For a vector v1 like {1,3,5,7,9}

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

    0 讨论(0)
  • 2020-12-14 01:54

    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.

    0 讨论(0)
  • 2020-12-14 01:57

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

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

    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:

      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';
    
    0 讨论(0)
提交回复
热议问题