How can I combine pairs of elements from a std::set? - c++

I have a set<string> from "one", "two", and "three".
How can I get all pairs from it?
one - two
one - three
two - three

Use a two-level loop:
// Loop over all members.
for (set<string>::iterator j = s.begin(); j != s.end(); ++j)
{
// Loop over all members up to, but excluding, the current outer-loop member.
for (set<string>::iterator i = s.begin(); i != j; ++i)
{
do_something_with(*i, *j);
}
}

Related

How to erase or change element while iterating over vector in C++?

I was in the middle of creating a simple sieve of Erathostenes function when I stumbled upon one obstacle. In to order to accomplish the highest efficiency in this task I wanted to use only a vector. Here is the current code:
vector<int> sieveOfErathostenes(int N) {
vector <int> result(N, 1);
for(int i = 2; i < sqrt(N); i++)
if(result[i] == 1)
for(int j = 2*i; j < N; j += i)
result.at(j) = 0;
// :c
return result;
}
This vector returns 1 and 0 in the proper position but I can't figure out how to implement both erasing or changing an element's value in a single loop. When I use an iterator to erase an element as in erase set element while iterating/// I can't access the vector to change its value, and when I use a standard for loop to access the element I can't remove it. I have tried going from the end of the vector and counting non zero elements and giving some offset when erasing but no success.
TL DR: What I can't figure out is:
for(int i = 0; i < N; i++)
{
if(result[i] == 0) {
//remove at position i
} else {
result.at(i) = i;
}
}
Thank you in advance for your time :)
Instead of erasing elements in the middle of the vector, you should write the results from the beginning of the vector and eliminate the unused elements in the end of vector.
int finalSize = 0;
for(int i = 0; i < N; i++)
{
if(result[i] != 0) {
result[finalSize++] = i;
}
}
result.resize(finalSize);
If you still need to remove an element from a std::vector during traversal, keep in mind that erase returns an iterator following the last removed element:
std::vector<int> result = {1,1,1,0,1,1,1};
for(auto it = result.begin(); it != result.end(); )
{
if(*it==0)
it = result.erase(it);
else
it++;
}

c++ list iterator arithmetic replacement ideas

I have a list that gets accessed in multiple places. There are some cases where I need to loop through the list from beginning to (end-n) elements and others where the whole list is accessed. I'm having trouble with the iterator arithmetic.
I want something that could do the following:
int n =10;
for (list<Term>::iterator itr = final.begin(); itr != (final.end()-n); itr++) {
//
}
does the following pseudo code make sense?
int N = myList.size() - n;
for (list<Term>::iterator itr = final.begin(),int length_reached=0; itr != (final.end() && length_reached<N; itr++,length_reached++) {
//
}
Using rbegin for me is not an option since I want the first instance of a match from the start of the list.
is there a better way of implementation here?
Since it's a list, random access is slow. Fortunately for you:
you're always starting at the beginning, and
std::list has a size() method
here's one way:
list<Term>::iterator itr = final.begin();
int to_do = std::max(0, int(final.size()) - n);
for ( ; to_do ; --to_do, ++itr )
{
// code here
}
Yes you can do this way
if ( n < final.size() )
{
auto m = final.size() - n;
for ( auto first = final.begin(); m != 0; ++first, --m )
{
//...
}
}
If the iterator itself can be changed in the loop then you can write the loop condition the following way
if ( n < final.size() )
{
auto m = final.size() - n;
for ( auto first = final.begin(); m != 0 && first != final.end(); ++first, --m )
{
//...
}
}
you can use reverse iterator and the std::advance
auto rit =final.rbegin();
std::advance(rit, n);
for (auto itr=final.begin(); itr!=rti.base(); ++itr) {
}

how to erase element from vector<char>?

I have a vector with char type;
vector<char> a_chars;
and it contains 6 characters but 3 of them are duplicate.
How can I delete the duplicate char? Here is my current code and it doesnt compile:
for(int i = 0; i < a_chars.size(); i++)
{
char current = a_chars.at(i);
for(int j = i+1; j < a_chars.size(); j++)
{
if (current == a_chars.at(j))
{
a_chars.erase[j];
}
}
}
here is the compile error: "C:invalid types '[int]' for array subscript|"
EDIT:
Also I have tried with a_chars.erase(j) and a_chars.erase(a_chars.at(j) and still had compile error.
You can use std::unique with combination of vector::erase method (known as erase-remove idiom). The vector has to be, however, sorted.
vector<char> a_chars;
std::sort(a_chars.begin(), a_chars.end());
a_chars.erase(std::unique(a_chars.begin(), a_chars.end()), a_chars.end());
If you don't want to sort your vector. You can use following snippet to remove duplicites.
void remove_duplicities(std::vector<char>& vec)
{
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
{
for (auto jter = std::next(iter); jter != vec.end(); ++jter)
{
if (*iter == *jter)
jter = std::prev(vec.erase(jter));
}
}
}
After some attempts I found out by my self.
It is not working with a_chars.erase[j]; nor a_chars.erase(j); neither a_chars.erase(a_chars.at(j));. All I had to do is make an iterator and make it same as 'j'.
vector<char>::iterator itr = a_chars.begin();
itr+=j;
a_chars.erase(itr);

Equating iterators

I'm facing some problems with set::iterators in c++. I have a set of 2-D points and I need to iterate and compare these points three by three.
My thought was to use three loops incrementing the iterators, one by one. But c++ gave me an error when I tried:
for (set<pair<double, double> >::iterator i = S.begin(); i != S.end(); i++){
for (set<pair<double, double> >::iterator j = i+1; j != S.end(); j++){
...
}
}
Edit: the error was "error: no match for ‘operator+’ in ‘i + 1’"
std::set has a bidirectional iterator. It has no such operation as iterator + integer number. So use instead
for (set<pair<double, double> >::iterator j = std::next( i ); j != S.end(); j++){

What's the difference between using Iterator and for loop for a vector

I would like to find out the difference between this code:
Vertices {
int x;
int y;
};
vector<Vertices>point;
Vertices min1,max1;
i = point.begin();
min1.y = i->y;
min1.x = i->x;
max1.x = i->x;
i++;
if(i->x < min1.x)
{
min1.x = i->x;
}
else
{
max1.x = i->x;
}
and this code:
min1.y = point[0].y;
min1.x = point[0].x;
max1.x = point[0].x;
for (int i = 1; i < point.size(); i++) {
if (point[i].x < min1.x)
min1.x = point[i].x;
else
max1.x = point[i].x;
}
EDIT
I have added in why for the 2nd piece of code to iterate from the 2nd element. What I'm doing is to compare and get the largest and smallest values. What I don't get it is why do they give me 2 different set of values? Am I misunderstanding something wrong?
First difference is that you don't have a loop in first case. It treats only very first element.
Second difference is that you start from 1 when you have a 0-th element in the second case. It treats all elements except very first.
Even with iterator you has to have a loop. The difference between using and not using iterators is just a convenience. Iterators are just different interface to access elements in a vector.
The iterator std::vector<typename>::iterator itr starts at the beginning of the vector, which is by default the first value of of your std::vector<typename> myVector.
When using a array you should start off with the very first element which is [0] not [1].
And here's a short example (out of my code) of using a iterator in a for loop:
void Rep_C_F_in_Ex (std::vector<std::string> *vTestTwo)
{
std::vector<std::string> vTestOne_;
for (std::vector<std::string>::iterator itr = vTestTwo->begin(); itr != vTestTwo->end(); itr++)
{
boost::split_regex (vTestOne_, *itr, boost::regex (",") );
for (std::vector<std::string>::iterator iterate = vTestOne_.begin(); iterate != vTestOne_.end(); iterate++)
{
vTestThree.push_back (*iterate);
++iterate;
vTestFour.push_back (*iterate);
}
}
}
If you want to loop it as array, you should start from 0 instead of 1.
int i = 0;
Bettor write it as below:
for (std::vector<xxx>::iterator it = point.begin(); it != point.end; ++it)