Slicing a vector in C++

Is there an equivalent of list slicing [1:] from Python in C++ with vectors? I simply want to get all but the first element from a vector.

Python's list slicing operator:

list1 = [1, 2, 3] list2 = list1[1:] print(list2) # [2, 3] 

C++ Desired result:

std::vector<int> v1 = {1, 2, 3}; std::vector<int> v2; v2 = v1[1:]; std::cout << v2 << std::endl; //{2, 3} 
6

7 Answers

This can easily be done using std::vector's copy constructor:

v2 = std::vector<int>(v1.begin() + 1, v1.end()); 
9

In C++20 it is pretty easy:

#include <span> #include <vector> #include <iostream> template<int left = 0, int right = 0, typename T> constexpr auto slice(T&& container) { if constexpr (right > 0) { return std::span(begin(std::forward<T>(container))+left, begin(std::forward<T>(container))+right); } else { return std::span(begin(std::forward<T>(container))+left, end(std::forward<T>(container))+right); } } int main() { std::vector v{1,2,3,4,5,6,7,8,9}; std::cout << "-------------------" << std::endl; auto v0 = slice<1,0>(v); for (auto i : v0) { std::cout << i << std::endl; } std::cout << "-------------------" << std::endl; auto v1 = slice<0,-1>(v); for (auto i : v1) { std::cout << i << std::endl; } std::cout << "-------------------" << std::endl; auto v2 = slice<1,3>(v); for (auto i : v2) { std::cout << i << std::endl; } std::cout << "-------------------" << std::endl; auto v3 = slice<1,-1>(v); for (auto i : v3) { std::cout << i << std::endl; } std::cout << "-------------------" << std::endl; auto v4 = slice<3,3>(v); for (auto i : v4) { std::cout << i << std::endl; } } 

Result:

Program returned: 0 ------------------- 2 3 4 5 6 7 8 9 ------------------- 1 2 3 4 5 6 7 8 ------------------- 2 3 ------------------- 2 3 4 5 6 7 8 ------------------- 

You can also add boundary checks and other cases like negative left indices etc... but this is only an example.

Run in compiler explorer:

2

It depends on whether you want a view or a copy.

Python's slicing for lists copies references to the elements, so it cannot be simply regarded as a view or a copy. For example,

list1 = [1, 2, 3] list2 = list1[1:] list2[1] = 5 print(list1) # does not change, still [1, 2, 3] 
list1 = [1, 2, [3]] list2 = list1[1:] list2[1][0] = 5 print(list1) # changes, becomes [1, 2, [5]] 

See this post for details.

DimChtz's anwer models the copy situation. If you just want a view, in C++20, you can use ranges (besides std::views::drop, std::views::take and std::views::counted are also useful):

auto v2 = v1 | std::views::drop(1); // #include <ranges> for (auto &e: v2) std::cout << e << '\n'; 

or std::span:

std::span v2{v1.begin() + 1, v1.end()}; // #include <span> for (auto &e: v2) std::cout << e << '\n'; 
1

I know it's late but have a look at valarray and its slices. If you are using a vector of some sort of NumericType, then it's worth giving it a try.

1

You can follow the above answer. It's always better to know multiple ways.

int main { std::vector<int> v1 = {1, 2, 3}; std::vector<int> v2{v1}; v2.erase( v2.begin() ); return 0; } 
2

To find a sub vector from index a to b, then, simply do this:

vector<int> sub_vec(v.begin() + a, v.begin() + b + 1); 

This will create a Sub Vector from the a index to the b index and we also add 1 in the end of the range while slicing as because end index will be excluded (value b-1 will be taken as the last index). So, we add 1 to include our last index also.

It seems that the cheapest way is to use pointer to the starting element and the number of elements in the slice. It would not be a real vector but it will be good enough for many uses.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like