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!
Related
I have a 2d vector like below:
std::vector<std::vector<int>> myVec_;
myVec_.push_back({16,0,0,0});
myVec_.push_back({8,8,0,0});
myVec_.push_back({8,4,4,0});
myVec_.push_back({8,4,4,0}); //duplicated
myVec_.push_back({4,8,4,0});
myVec_.push_back({4,8,2,2});
myVec_.push_back({4,4,4,4});
myVec_.push_back({4,8,2,2}); //duplicated
myVec_.push_back({4,8,0,4});
I want to erase both duplicated rows.
Trying some solutions that I found in StackOverflow didn't work for the second duplicated rows
e.x.
std::vector<int> v = { 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 8 };
// 1 2 2 3 4 5 6 7 8 9 8
for(size_t i=0;i<v.size();i++)
{
for(size_t j=0;j<v.size();j++)
{
if(v[i] == v[j] && i != j)
{
v.erase(v.begin()+j);
j--; // Fix for certain datasets ie:
} // 1 2 1 1
}
}
// Produces:
// 1 2 3 4 5 6 7 8 9
What is the way to do it?
Edit:
I came out with the above solution which looks ok:
for(int i = myVec_.size()-1; i >= 0; i--) {
for(int j = 0; j < i; j++) {
bool erase = true;
for(int k = 0; k < myVec_[i].size(); k++) {
if(myVec_[i][k] != myVec_[j][k]) {
erase = false;
}
}
if(erase) {
myVec_.ersae(myVec_.begin() + i);
j = i;
}
}
}
Note: I should have mentioned that sorting my vector wasn't ok for my case
There could be several solutions to this:
Solution 1:
Use a std::set to determine whether to store the item in the vector:
#include <vector>
#include <set>
#include <iostream>
void addItem(std::vector<std::vector<int>>& alldata,
const std::vector<int>& item,
std::set<std::vector<int>>& insertedItems)
{
if ( !insertedItems.count(item) )
{
alldata.push_back(item);
insertedItems.insert(item);
}
}
int main()
{
std::vector<std::vector<int>> myVec_;
std::set<std::vector<int>> vectorSet;
addItem(myVec_, {16,0,0,0}, vectorSet);
addItem(myVec_, {8,8,0,0}, vectorSet);
addItem(myVec_, {8,4,4,0}, vectorSet);
addItem(myVec_, {8,4,4,0}, vectorSet);
addItem(myVec_, {4,8,4,0}, vectorSet);
addItem(myVec_, {4,8,2,2}, vectorSet);
addItem(myVec_, {4,4,4,4}, vectorSet);
addItem(myVec_, {4,8,2,2}, vectorSet);
addItem(myVec_, {4,8,0,4}, vectorSet);
for (auto& v : myVec_)
{
for (auto& i : v)
std::cout << i << " ";
std::cout << "\n";
}
}
Output:
16 0 0 0
8 8 0 0
8 4 4 0
4 8 4 0
4 8 2 2
4 4 4 4
4 8 0 4
The addItem function basically takes the original vector, the data that will potentially be inserted, and a std::set that is populated with the items that have already been inserted.
The std::set::count returns true if the item is already in the set, otherwise false is returned. The item is only added to the vector if it isn't already in the set.
The drawback is that you need extra space to store the std::set. However the search for the item in the set is much faster than the Solution 2 (below).
Solution 2:
The other solution is to add items to the vector, but search the vector for the item before inserting:
#include <vector>
#include <iostream>
#include <algorithm>
void addItem(std::vector<std::vector<int>>& alldata,
const std::vector<int>& item)
{
if ( std::find(alldata.begin(), alldata.end(), item) == alldata.end())
alldata.push_back(item);
}
int main()
{
std::vector<std::vector<int>> myVec_;
addItem(myVec_, {16,0,0,0});
addItem(myVec_, {8,8,0,0});
addItem(myVec_, {8,4,4,0});
addItem(myVec_, {8,4,4,0});
addItem(myVec_, {4,8,4,0});
addItem(myVec_, {4,8,2,2});
addItem(myVec_, {4,4,4,4});
addItem(myVec_, {4,8,2,2});
addItem(myVec_, {4,8,0,4});
for (auto& v : myVec_)
{
for (auto& i : v)
std::cout << i << " ";
std::cout << "\n";
}
}
Output:
16 0 0 0
8 8 0 0
8 4 4 0
4 8 4 0
4 8 2 2
4 4 4 4
4 8 0 4
Since std::vector has an overloaded == operator, usage of std::find can be done to search to see if the item in the vector matches the item that will be inserted. If there is no match, then the item is inserted.
With this solution, less space is used, since a std::set does not need to be maintained. The drawback is that you have to search the vector linearly, thus taking more time to find the duplicate than if you used std::set if the number of items are many.
So if there are many items, this may not be the ideal solution.
It is possible (and faster) to remove duplicated directly, without using std::set, just std::sort and std::unique (removes consecutive duplicates) :
//sorting
{
std::vector<int>::const_iterator i, j;
std::sort (myVec_.begin (), myVec_.end (), [&i, &j] (const std::vector<int>& v0, const std::vector<int>& v1) {
i = v1.begin ();
j = v0.begin ();
while ((i != v0.end ()) && (*j == *i)) {
++i;
++j;
}
return i == v0.end ()?false:*i < *j;
});
}
//unique
auto i (myVec_.begin ());
i = std::unique (myVec_.begin (), myVec_.end ());
if (i != myVec_.end ()) myVec_.erase (i, myVec_.end ());
my problem is to take a matrix mat of rowcol length, and move each column within it one position to the left.
For example if i have a 3x3 matrix like this:
4 5 2
6 7 3
3 4 6
the result should must be like this:
5 2 4
7 3 6
4 6 3
I can't get the method to work, how many times I do it, does anyone have any ideas?
Below my code:
for(int i = rowcol - 1; i > 0; i--)
for(int j = 0; j < rowcol; j++) {
if(i == 0) swap(mat[j][rowcol - 1], mat[j][i]);
swap(mat[j][i], mat[j][i-1]);
}
The standard library has an algorithm to do what you're asking: std::rotate. The following example rotates everything right one column.
#include <iostream>
#include <algorithm>
int main()
{
int arr[][3] = {
{ 1,2,3 },
{ 4,5,6 },
{ 7,8,9 }
};
for (auto& row : arr)
{
std::rotate(row, row+2, row+3);
}
for (auto& row : arr)
{
for (auto x : row)
std::cout << x << ' ';
std::cout << '\n';
}
}
Output
3 1 2
6 4 5
9 7 8
Obviously the conditions of your matrix access to individual rows can be (and is likely) different than the above trivial example, but nonetheless, the concept is still the same. I leave it to you to play with for learning how to do it "left" (it won't be hard *).
hint: std::rotate(row, row+1, row+3);
Here's my updated solution. It's even easier than the original one I posted a few minutes earlier.
Basically, for each row:
Save off the value in the first column
Shift all the values (starting at column 1) in the row by one to the left.
The last value in the row is the previously saved variable from the first step
Code:
for (size_t row = 0; row < rowcol; row++) {
int tmp = mat[row][0];
for (size_t col = 1; col < rowcol; col++) {
mat[row][col-1] = mat[row][col];
}
mat[row][rowcol-1] = tmp;
}
What about as follows ?
for ( auto ui = 0u ; ui < rowcol ; ++ui )
for ( auto uj = 1u ; uj < rowcol ; ++uj )
std::swap(mat[ui][uj-1], mat[ui][uj]);
The following is a full compiling example
#include <iostream>
static constexpr std::size_t rowcol = 3u;
void printMat (int mat[rowcol][rowcol])
{
for ( auto ui = 0u ; ui < rowcol ; ++ui ) {
for ( auto uj = 0u ; uj < rowcol ; ++uj )
std::cout << mat[ui][uj] << ' ';
std::cout << std::endl;
}
std::cout << std::endl;
}
int main()
{
int mat[rowcol][rowcol] { {4, 5, 2}, {6, 7, 3}, {3, 4, 6} };
printMat(mat);
for ( auto ui = 0u ; ui < rowcol ; ++ui )
for ( auto uj = 1u ; uj < rowcol ; ++uj )
std::swap(mat[ui][uj-1], mat[ui][uj]);
printMat(mat);
}
Your logic is correct except, you're actually shifting the columns of the matrix one position to the right, not left. Not only that, the (i==0) condition is not required.
Replace the backward iteration with forward iteration and get rid of the conditional statement and you're good to go. Here's the modified code:
for(int i = 0; i < rowcol-1; i++)
for(int j = 0; j < rowcol; j++) {
// if(i == 0) swap(mat[j][rowcol - 1], mat[j][i]);
swap(mat[j][i], mat[j][i+1]);
}
Basically your logic is similar to Bubble Sort. You were bubbling the final column towards the beginning of the matrix by shifting all other columns rightward.
I inverted it by making it so that we are bubbling the first column towards the end instead. Feel free to ask any questions.
Below there is a tabular view of a sorted vector.
vector v1= {1 , 8 ,10 ,16}
int x=9;
You are given a task to reorder vector v1 by following a rule.
You will be given a integer x.
The rule is:
You will print all the elements of the vector, such that, the numbers appearing closest to x in the vector v1 must be printed first.
For example the reordered vector must be 8,10,16,1.
sample examples:
x=15 . . .v1={-100,1,12,15,100} . . . output:{15,12,1,100,-100}
x=99 . . .v1={-100,1,12,15,100} . . . output:{100,15,12,1,-100}
x=-1 . . .v1={-100,1,12,15,100} . . . output:{1,12,15,-100,100}
In case there are two numbers that are equally closer to x, in that case, print smaller element first
for example:
x=0 . . .v1={-100,-50,50,100} . . . output:{**-50**,50,**-100**,100}
I used a naive approach, but it is too slow for larger ranges.
while(0 < v1.size()) {
for (int j = 0; j <= v1.back(); j++) {
if (x - j >= 0 && find(all(v1), x - j) != v1.end()) {
b = x - j; break;
}
if (x + j <= v1.back() && find(all(v1), x + j) != v1.end()) {
b = x + j; break;
}
}
cout<<b;
auto it2 = find(all(v1), b);
v1.erase(it2);
}
Please, if you can, suggest me a faster code.
My code is way too slow.
Elaborating on what Aconcagua suggested:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct sortClosestToFunctor {
explicit sortClosestToFunctor(int x) : m_x{x} {}
bool operator()(int const lhs, int const rhs) const {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
}
private:
int m_x;
};
int main() {
std::vector<int> v1{1, 8, 10, 16};
int x = 9;
// using functor
std::sort(v1.begin(), v1.end(), sortClosestToFunctor(9));
// using lambda
std::sort(v1.begin(), v1.end(), [x](int const lhs, int const rhs) {
int dx = std::abs(lhs - m_x);
int dy = std::abs(rhs - m_x);
return (dx < dy) or (dx == dy and lhs < rhs);
});
// 8 10 16 1
std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
}
Well, you need an appropriate comparator, then you can simply use std::sort:
std::vector<int> numbers;
int referenceValue; // = ...
std::sort
(
numbers.begin, numbers.end,
[/* ... */](int x, int y) { /* ... */ }
);
You'll get the vector sorted into exactly the order you need, no need to find and remove elements from, you can just iterate over it afterwards. std::sort guarantees O(n(log(n)) (since C++11), so that should be fast enough (faster you cannot get on sorting anyway...).
Question now is: how would such a comparator look like?
Well, at very first, it will need to have the reference value available, so it will capture it:
[referenceValue](int x, int y) { /* ... */ }
As it's a simple int, capturing by value is fine, more complex types you might prefer to capture by reference instead.
The comparator should implement 'less' semantics, so it should return true if x goes before y. So we can have:
int dx = std::abs(x - referenceValue);
int dy = std::abs(y - referenceValue);
return dx < dy || dx == dy && x < y;
// if x has smaller distance: ^^^^^^^
// or, in case of equality, the smaller one ^^^^^^^^^^^^^^^^^^^^
That's it, you're done...
Untested code, if you happen to find a bug, please fix it yourself ;)
My five cents. A straightforward approach without sorting a vector.
I am sure that it is a bad idea to sort the vector if the only task is to output it in some order. Otherwise the original vector will be changed (Why?! This is not required in the assignment.) or a copy of the vector will be created.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
std::ostream & closest_output( const std::vector<int> &v,
const int &value,
std::ostream &os = std::cout )
{
auto it = std::lower_bound( std::begin( v ), std::end( v ), value );
if ( it == std::begin( v ) )
{
for ( auto last = std::end( v ); it != last; ++it )
{
os << *it << ' ';
}
}
else if ( it == std::end( v ) )
{
for ( auto first = std::begin( v ); it != first; )
{
os << *--it << ' ';
}
}
else
{
auto next = it, first = std::begin( v ), last = std::end( v );
while ( it != first && next != last )
{
if ( *next - value < value - *std::prev( it ) )
{
os << *next++ << ' ';
}
else
{
os << *--it << ' ';
}
}
while ( it != first ) os << *--it << ' ';
while ( next != last ) os << *next++ << ' ';
}
return os;
}
int main()
{
std::vector<int> v1 = { 1 , 8 ,10 ,16 };
int value = 9;
closest_output( v1, value ) << '\n';
std::vector<int> v2 = { -100, 1, 12, 15, 100 };
value = 15;
closest_output( v2, value ) << '\n';
value = 99;
closest_output( v2, value ) << '\n';
value = 1;
closest_output( v2, value ) << '\n';
return 0;
}
The program output is
8 10 16 1
15 12 1 100 -100
100 15 12 1 -100
1 12 15 100 -100
Let's consider if x = 9 and vector = {1, 8, 10, 16},
Then upper bound of x in vector is 10,
Now if you traversal toward begin or toward end of the vector from upper bound the distance will increase with respect to x in both direction, because vector is sorted.
Following two step will produce required output,
Find distance between x and left element, and between right element and x then if left distance is less then or equal to right distance then print left element otherwise print right element,
If left element is printed then move one element previous to left element and if right element is printed then move next element from right element.
Now let`s apply these steps,
Here x = 9, vector = {1, 8, 10, 16} and upper bound = 10
left element = 8, right element = 10
(9 - 8) <= (10 - 9) is true, so print 8, and now left element = 1
left element = 1, right element = 10
(9 - 1) <= (10 - 9) is false, so print 10, and now right element = 16
left element = 1, right element = 16
(9 - 1) <= (16 - 9) is false, so print 16, and now right element = end of
vector
left element = 1, right element = end of vector
so print 1
These steps will produce expected output : {8, 10, 16, 1}
Try this implementation,
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
template <typename ForwardIterator>
void print(ForwardIterator first, ForwardIterator last){
for(; last != first; ++first)
cout<< *first<< " ";
}
void printClostestFirst(const std::vector<int>& vec, const int piotValue){
std::vector<int>::const_iterator mid = std::upper_bound(vec.cbegin(), vec.cend(), piotValue);
if(vec.cend() == mid){
print(vec.crbegin(), vec.crend());
return;
}
else if(vec.begin() == mid){
print(vec.cbegin(), vec.cend());
return;
}
std::vector<int>::const_reverse_iterator left = vec.crbegin() + std::distance(mid, vec.cend());
std::vector<int>::const_iterator right = mid;
std::vector<int>::const_reverse_iterator leftEnd = vec.crend();
std::vector<int>::const_iterator rightEnd = vec.cend();
int leftDist = 0;
int rightDist = 0;
while(leftEnd != left && rightEnd != right){
leftDist = piotValue - *left;
rightDist = *right - piotValue;
if(leftDist <= rightDist){
cout<< *left<< " ";
++left;
}
else{
cout<< *right<< " ";
++right;
}
}
if(leftEnd != left)
print(left, leftEnd);
else
print(right, rightEnd);
}
int main(int , char *[]){
cout<< "x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { ";
printClostestFirst({1, 8, 10, 16}, 9);
cout<< "}\n";
cout<< "x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 15);
cout<< "}\n";
cout<< "x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, 99);
cout<< "}\n";
cout<< "x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,1,12,15,100}, -1);
cout<< "}\n";
cout<< "x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { ";
printClostestFirst({-100,-50,50,100}, 0);
cout<< "}\n";
}
output:
x = 9 . . .vec = { 1, 8, 10, 16 } . . . output: { 8 10 16 1 }
x = 15 . . .vec = { -100,1,12,15,100 } . . . output: { 15 12 1 100 -100 }
x = 99 . . .vec = { -100,1,12,15,100 } . . . output: { 100 15 12 1 -100 }
x = -1 . . .vec = { -100,1,12,15,100 } . . . output: { 1 12 15 -100 100 }
x = 0 . . .vec = { -100,1,12,15,100 } . . . output: { -50 50 -100 100 }
I have a vector of integers. For example: 26 58 32 47 . I need to replace them with their number in that sequence. In this case it would be: 4 1 3 2 . I tried this code:
int n = 1;
vector <int> vietos;
for (vector <int>::iterator i = vieta.begin(); i != vieta.end(); i++) {
for (vector <int>::iterator j = vieta.begin(); j != vieta.end(); j++) {
if (*i > *j)
n++;
}
vietos.push_back(n);
cout << n << " ";
n = 1;
}
Having numbers 23 25 38 28 26 28 (Note: In this case I number them in reverse order!) I get: 1 2 6 4 3 4 which is good except for two numbers are equal.
Maybe there is some way to number elements in vector using STL algorithms?
In my opinion the simplest way is to use std::reference_wrapper. The code will look simple and very clear.
Here is the program that demonstrates the approach.
Enjoy!:)
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
1 2 6 4 3 5
If you need to get the reverese order all you need is to add to the code functional object
std::greater<std::reference_wrapper<int>>()
in the call of std::stable_sort
For example
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end(),
std::greater<std::reference_wrapper<int>>() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
6 5 1 2 4 3
Is not it the best solution is it? :)
EDIT: Maybe there is no sense to use std::stable_sort with the functional object. It will be enough to use for loop setting numbers in the reverse order. Something as
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[vr.size() + i - 1].get() = i + 1;
}
In that case, you should increment when the value is greater than or equal to rather than just greater than, try this:
(*i >= *j)
If you were to replace the iterators with integers, i.e.: (I assume < isn't defined on iterators, but it could be)
for (int i = 0; i < vietos.size(); i++)
You could increment n as well when elements to the left are equal, i.e. when
vietos[i] > vietos[j] || (vietos[i] == vietos[j] && j < i).
Alternatively, you could create a vector<pair<int, int> >, with each pair containing the element and its index, then sort that, and iterate through the sorted vector, setting the index in the pair in the original vector to the index in the sorted vector.
This would give an O(n log n) running time, as opposed to the O(n²) of the above.
Pseudo-code:
vector arr
vector<pair> pairs
for i = 0 to n
pairs.insert(arr[i], i)
sort pairs
for i = 0 to n
arr[pairs[i].second] = i
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';