Related
Assuming we have a sorted descending vector, like:
vector<int> array {26, 21, 13, 11, 8, 3, 2}.
I would like to insert a new and different element to the ones already present, so that descending sort of vector is kept.
Example flow:
I want to insert element 22, basically added at index 1, thus vector would be: 26, 22, 21, 13, 11, 8, 3, 2
I want to insert element 17, basically added at index 3, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2
I want to insert element 1, basically added at a new index, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2, 1
I want to insert element 43, basically added at index 0, thus vector would be: 43, 26, 22, 21, 17, 13, 11, 8, 3, 2, 1
A fast sample implementation in C++ would be:
#include<iostream>
#include<vector>
#include <chrono>
using namespace std;
using namespace std::chrono;
int get_Index_Insert(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
for (int i = 0; i < lengthArray; i++)
{
if (array[i] < insertValue)
{
whereInsert = i;
break;
}
}
return whereInsert;
}
int get_Index_Insert2(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
// Break out early if these cases:
if (lengthArray == 0 || (array[lengthArray - 1] > insertValue))
return whereInsert;
// Otherwise do your binary magic:
int low = 0;
int high = lengthArray - 1;
while (low <= high)
{
int mid = low + (high - low) / 2;
if (array[mid] > insertValue)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
whereInsert = high + 1;
return whereInsert;
}
vector<int> insert_Value(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
vector<int> insert_Value2(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert2(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
int main()
{
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value(array, 22);
array = insert_Value(array, 17);
array = insert_Value(array, 1);
array = insert_Value(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 1, linear search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value2(array, 22);
array = insert_Value2(array, 17);
array = insert_Value2(array, 1);
array = insert_Value2(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 2, binary search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
cout << endl << endl << endl;
return 0;
}
Other info that may help in deciding recommended method:
I cannot use anything else than class vector from STL; (only using it as a holder + it's push_back function, nothing else as helper function from it);
I will not have more than a 1000 elements ever in the vector.
Is there any way better to do it than above? in less complexity involved? Any source material I may have missed and that might help is very much appreciated also.
EDIT:
After some more investigations and using binary search method while seeking index position for actual element insertion (thanks to the debates from comments), edited my above sample a bit, testing execution time of a "get_Index_Insert2(...) function using early returns and binary search.
Times received (microseconds), after 3 runs:
Time taken by function 1, linear search: 60 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 33 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Instead of creating a new vector you can use the insert function to put the new value into the existing list at the desired index. See https://en.cppreference.com/w/cpp/container/vector/insert
void insert_Value(const vector<int>& arrayInput, int insertValue)
{
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
arrayInput.insert(whereInsert, insertValue);
}
#include <algorithm>
#include<iostream>
#include<vector>
using namespace std;
std::vector<int>::const_iterator get_Index_Insert(const vector<int>& array ,int insertValue) {
return std::find_if(array.cbegin(),array.cend(),[insertValue](int aValue) { return aValue < insertValue;});
}
void insert_Value(vector<int>& arrayInput, int insertValue, std::vector<int>::const_iterator aIt)
{
arrayInput.insert(aIt,insertValue);
}
int main()
{
vector<int> array{26, 21, 13, 11, 8, 3, 2 };
auto myIt = get_Index_Insert(array,22);
insert_Value(array,22,myIt);
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl << endl << endl;
return 0;
}
This is only an idea, then it can be enhanced
You don't need to pass the size of the vector, std::vector already have a member function size().
I think you overcomplicated things. You just have to iterate over the vector and compare each element with the value you want to insert. If the comparison evaluates to false, then you found where to insert the new element.
You may implement the function the following way:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
bool inserted(false);
for(typename std::vector<val_t>::iterator it = vec.begin(); !inserted && (it != vec.end()); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
inserted = true;
}
}
if(!inserted)
vec.push_back(val);
}
It takes the vector, the value to instert and the comparison function you want.
For your use case, it may be used like this:
int main()
{
std::vector<int> v {26, 21, 13, 11, 8, 3, 2};
insert_ordered(v, 22, std::greater<int>());
insert_ordered(v, 17, std::greater<int>());
insert_ordered(v, 1, std::greater<int>());
insert_ordered(v, 43, std::greater<int>());
for(const int & i : v)
std::cout << i << ' ';
return 0;
}
Output:
43 26 22 21 17 13 11 8 3 2 1
Live example
If, for some reason, you can't use std::greater, you can define your own comparator like this:
auto desc_comp = [](const int & lhs, const int & rhs)
{
return lhs > rhs;
};
And use it like this:
insert_ordered(v, 22, desc_comp);
Edit:
If you don't mind having several exit points in the function, it can be simplified as:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
for(typename std::vector<val_t>::iterator it = vec.begin(); it != vec.end(); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
return;
}
}
vec.push_back(val);
}
I'm trying to debug this program to find the number of matching elements that occur at the same index in 2 different vectors. Requirement is to NOT use any loops
Code on online compiler: http://cpp.sh/8rvtj
#include <iostream>
#include <vector>
using namespace std;
int calls=0;
int matchCount(const vector<int>& v1, const vector<int>& v2, int i=0)
{
calls++;
static int smallVecSz=-1;
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
static int ans=0;
if(i==smallVecSz)
{
cout << "Returning " << ans << endl;
return ans;
}
// if element at index i is same in v1 and v2, add 1 to ans else add 0 to ans
ans += (v1[i]==v2[i] ? 1 : 0);
return ans + matchCount(v1,v2,i+1); // pass optional param index i+1 to advance to next ele
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "Number of Recursion calls: " << calls << endl;
return 0;
}
Here is a sample input:
vector v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector v2 = {2, 5, 3, 0, 8, 4, 1};
Here is a sample output:
Returning 4
There are 32 matching numbers at same indexes
Number of Recursion calls: 8
My program is recursive function is correctly returning the ans 4. But the main program is printing 32.
Oops, a static variable accumulating in a recursive function is a code smell.
Normally, when you use recursion, each call starts with a clean an fresh environment.
In that case, you accumulate the value of each call with its children to find the total.
Alternatively, you can use a static variable which is updated by each call and just used by the top parent.
But here you are mixing both approaches, actually getting a much too high value.
So 2 ways here:
make ans an automatic (non static) variable:
...
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
int ans=0;
if(i==smallVecSz)
...
keep ans static, and do not accumulate:
...
ans += (v1[i]==v2[i] ? 1 : 0);
matchCount(v1, v2, i+1); // pass optional param index i+1 to advance to next ele
return ans;
...
Of course in that case, you will get wrong results if you call the function more than once because ans will not be reset to 0 (Thanks to #bruno for noticing)
your problem comes from ans being static and the fact you return it when you reach the end of the vector rather than 0 etc
I do not understand too why that function is recursive
a solution with a loop and an other with recursion as you requested in a comment
#include <iostream>
#include <vector>
using namespace std;
int matchCount(const vector<int>& v1, const vector<int>& v2)
{
vector<int>::const_iterator it1;
vector<int>::const_iterator it2;
int result = 0;
for (it1 = v1.begin(), it2 = v2.begin();
(it1 != v1.end()) && (it2 != v2.end());
++it1, ++it2) {
if (*it1 == *it2)
result += 1;
}
return result;
}
int recurMatchCount(const vector<int>& v1, const vector<int>& v2, int i = 0)
{
return ((i == v1.size()) || (i == v2.size()))
? 0
: (((v1[i] == v2[i]) ? 1 : 0)
+ recurMatchCount(v1, v2, i + 1));
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "There are " << recurMatchCount(v1,v2) << " recur matching numbers at same indexes" << endl;
return 0;
}
I'm writing an operation to find the lowest missing element of a vector, V = 1..N + 1. This has to be performed in O(N) time complexity.
Solution One:
std::vector<int> A {3,4,1,4,6,7};
int main()
{
int max_el = *std::max_element(A.begin(), A.end()); //Find max element
std::vector<int> V(max_el);
std::iota(V.begin(), V.end(), 1) //Populate V with all int's up to max element
for(unsigned into i {0}; i < A.size(); i++)
{
int index = A[i] - 1;
if(A[i] == V[index]) //Search V in O(1)
{
V[index] = max_el; //Set each to max_el, leaving the missing int
}
}
return *std::min_element(V.begin(), V.end()); //Find missing int as its the lowest (hasn't been set to max_el)
}
//Output: 2
This works completely fine.
However, I'm now trying to get this to work with vector containing negative int's.
Solution Two:
My logic is to take the same approach, however 'weight' the indexes given the size of the vector and the number of negative int's in the vector:
std::vector<int> A {-1, -4, -2, 0, 3, 2, 1}
int main()
{
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int min_el_abs = abs(min_el); //Convert min element to absolute
int total = min_el_abs + max_el;
std::vector<int> V(total + 1);
std::iota(V.begin(), V.end(), min_el);
int index;
//Find amount of negative int's
int first_pos;
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] >= 0) {first_pos = i; break;}
}
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] <= 0) //If negative
{
index = (A.size() - first_pos) - abs(A[i]);
} else
{
index = (A[i] + 1) + first_pos;
}
if(A[i] == V[index])
{
V[index] = 0;
}
}
return *std::min_element(V.begin(), V.end());
}
//Output: -3
Solution Two fails to compare the values of the two vectors (A and V), as calculating the index with the above methods with a positive int doesn't work.
1) How can I get my Solution 2 to work with unordered vector's of negative int's?
2) How can I edit my Solution 2 to work with vectors of positive as well as vectors with negative int's?
Your first solution seems O(max(N,M)), where I consider N the number of elements in vector A and M the size of vector V (or max(Ai)), but you are looping through both vectors multiple times (with std::min_element, std::max_element, the for loop, the allocation of V and std::iota too).
Besides, once corrected a couple of typos (a missing ; and an into instead of int), your program returns the value found... from main(), which is a bit odd.
Your first algorithm always searches for the lowest missing value in the range [1, max value in A], but it can be generalized to find the lowest missing element in the range [min(Ai), max(Ai)], even for negative numbers.
My approach is similar to that of L.Senioins, but I've used different library functions trying to minimize the number of loops.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template <class ForwardIt>
typename std::iterator_traits<ForwardIt>::value_type
lowest_missing(ForwardIt first, ForwardIt last)
{
if ( first == last )
throw std::string {"The range is empty"};
// find both min and max element with one function
auto result = std::minmax_element(first, last);
// range is always > 0
auto range = *result.second - *result.first + 1;
if ( range < 2 )
throw std::string {"Min equals max, so there are no missing elements"};
std::vector<bool> vb(range); // the initial value of all elements is false
for (auto i = first; i != last; ++i)
vb[*i - *result.first] = true;
// search the first false
auto pos = std::find(vb.cbegin(), vb.cend(), false);
if ( pos == vb.cend() ) // all the elements are true
throw std::string {"There are no missing elements"};
return std::distance(vb.cbegin(), pos) + *result.first;
}
template <class ForwardIt>
void show_the_first_missing_element(ForwardIt first, ForwardIt last)
{
try
{
std::cout << lowest_missing(first, last) << '\n';
}
catch(const std::string &msg)
{
std::cout << msg << '\n';
}
}
int main() {
std::vector<int> a { 1, 8, 9, 6, 2, 5, 3, 0 };
show_the_first_missing_element(a.cbegin(), a.cend());
std::vector<int> b { -1, -4, 8, 1, -3, -2, 10, 0 };
show_the_first_missing_element(b.cbegin(), b.cend());
show_the_first_missing_element(b.cbegin() + b.size() / 2, b.cend());
std::vector<int> c { -2, -1, 0, 1, 2, 3 };
show_the_first_missing_element(c.cbegin(), c.cend());
std::vector<int> d { 3, 3, 3 };
show_the_first_missing_element(d.cbegin(), d.cend());
std::vector<int> e;
show_the_first_missing_element(e.cbegin(), e.cend());
return 0;
}
The results outputted for my test cases are:
4
2
-1
There are no missing elements
Min equals max, so there are no missing elements
The range is empty
My solution is to make a bool vector (or char vector just to avoid compilation warnings about casting to bool) which has the size of all possible elements. All elements are initialized to 0 and later are assigned to 1 which indicates that the element is not missing. All you need to do then is to find an index of the first 0 element which is the lowest missing element.
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> A{ -1, 0, 11, 1, 10, -5 };
int main() {
if (A.size() > 1) {
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int range = abs(max_el - min_el) + 1;
std::vector<int> V(range, 0);
for (size_t i = 0; i < A.size(); i++)
V[A[i] - min_el] = 1;
if (*std::min_element(V.begin(), V.end()) == 0)
std::cout << std::distance(V.begin(), std::find(V.begin(), V.end(), 0)) + min_el;
else
std::cout << "There are no missing elements" << std::endl;
}
else
std::cout << "There are no missing elements" << std::endl;
std::cin.get();
}
I'm going to try give my own question an answer, after spending sometime thinking about this:
int main()
{
std::vector<int> A {-3, -1, 0, 1, 3, 4};
auto relative_pos = std::minmax_elment(A.begin(), A.end());
std::vector<bool> Litmus( *(relative_pos.second) - *(relative_pos.first), false); //Create vector of size max val - min val)
auto lowest_val = *(relative_pos.first);
for(auto x : A)
{
Litmus[i - lowest_val] = true;
}
auto pos = std::find(Litmus.begin(), Litmus.end(), false); //Find the first occurring false value
std::cout<< (pos - Litmus.begin()) + lower<<std::endl; //Print the val in A relative to false value in Litmus
}
This solution works with negative numbers and is linear.
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
int solution(vector<int> &A) {
std::vector<int>::iterator it = std::max_element(A.begin(),A.end());
try
{
sort(A.begin(),A.end());
std::vector<int>::iterator it = std::unique(A.begin(),A.end());
A.resize(std::distance(A.begin(),it));
for(int i = 0, j = 1; i < A.size(); i++)
{
if( A[i] != j)
{
return j;
}
j++;
}
}
catch(exception &e)
{
std::cout<<e.what()<<std::endl;
}
return ++(*it);
}
I have a unsymmetrical vector in 2D.
vector< vector<int> > Test
where Test =
2 4 6 5 7
6 5 7 9 10
5 9 10
9 10
I am reading the row 1 and if any element of this is present in other rows then delete it.
for eaxmple.. After reading row 1, i have to remove 6, 5, and 7 from other rows.
However, It is not working
Here is the code i am trying
Test[i].erase(Test[i].begin()+j);
where i = row and j is col.
My code is :
for (i =0; i < Test.size();i++)
{
for (j=0; j < Test[i].size();j++)
{
// removed repeated element
if (i >0)
{
Test[i].erase(Test[i].begin() +j);
}
}
}
Maybe it is nor very nice but it works
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<std::vector<int>> v =
{
{ 2, 4, 6, 5, 7 },
{ 6, 5, 7, 9, 10 },
{ 5, 9, 10 },
{ 9, 10 }
};
for ( const auto &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
std::cout << std::endl;
if ( !v.empty() )
{
for ( auto it = std::next( v.begin() ); it != v.end(); ++it )
{
auto is_present = [&]( int x )
{
return std::find_if( v.begin(), it,
[x]( const std::vector<int> &v1 )
{
return std::find( v1.begin(), v1.end(), x ) != v1.end();
} ) != it;
};
it->erase( std::remove_if( it->begin(), it->end(), is_present ),
it->end() );
}
}
for ( const auto &row : v )
{
for ( int x : row ) std::cout << x << ' ';
std::cout << std::endl;
}
return 0;
}
The output is
2 4 6 5 7
6 5 7 9 10
5 9 10
9 10
2 4 6 5 7
9 10
You can place the values encountered in each row in a set, and then query every element in a new row for existence in that set. Such a function would look like this :
void RemoveRowDuplicates(vector<vector<int>> &v)
{
std::set<int> vals;
for(auto &vec : v)
{
vec.erase(remove_if(vec.begin(), vec.end(), [&](int k){
return vals.find(k) != vals.end();
}), vec.end());
vals.insert(vec.begin(), vec.end());
}
}
What exactly do you think is Test[i].begin()+j? Is ist a set of elements you want to erase? I don't think so. It should be just an iterator, that points to a single element, but you want to delete all elements, that are already in your datastructure.
If I understood, what you want to do, try:
for(int j = 0; j < Test.size(); j++){ //iterate over other rows
if(j == i)
continue;
for(int k = 0; k < Test[j].size(); k++){ //iterate over elements of the rows
int elementToRemove = (Test[j])[k];
vector<int>::iterator it = Test[i].begin();
while (it != Test[i].end()) { //iterate over row i
if((*it) == elementToRemove){ //erase the element if it matches the actual
it = Test[i].erase(it);
}else{
it++;
}
}
}
}
You could execute the code for every possible i. Maybe start form i = 0 to n. If I refer to your code, that you added put the code above in between your
for (i =0; i < Test.size();i++){
//my code here...
}
Edit: Used iterator now to delete. The first version was not correct.
Edit2: Changed the index of the first loop and added continue statement.
This works for me:
int i = 0;
for ( int j = i+1; j < Test.size(); ++j )
{
for ( int k = 0; k < Test[i].size(); ++k )
{
std::vector<int>::iterator iter = Test[j].begin();
std::vector<int>::iterator end = Test[j].end();
for ( ; iter != end; )
{
if ( *iter == Test[i][k] )
{
iter = Test[j].erase(iter);
}
else
{
++iter;
}
}
}
}
Consider the following 2D vector
myVector=
1 2 3 4 5 -6
6 7 8 -9
8 -1 -2 1 0
Suppose we want to delete the element myVector[row][column] for appropriate row and column indices.
Look at the following code:
void delete_element(vector<int>& temp, col)
{
temp.erase(temp.begin()+col);
}
int main()
{
//Assume that the vector 'myVector' is already present.
cin>>row>>column;
delete_element(myVector[row],column);
}
What we basically do is,we get the row and column of the element to be deleted. Now as this 2D vector is a vector of vectors, we pass the vector(the row containing the element to be deleted) and the column as parameters to a function. Note that the row-vector is passed as a reference ('&' in vector parameter).
Now the problem becomes quite as simple as deleting an element from a 1D vector.
Hope this helps!
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 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.
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.
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}
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
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.
use boost range adapters. they are lazy:
operator|() is used to add new behaviour lazily and never modifies its
left argument.
boost::for_each(v|sliced(1,5)|transformed(doSomething));
doSomething needs to take range as input. a simple (may be lambda) wrapper would fix that.
You can represent those "slices" with a pair of iterators.
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.
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';