emplace_back when loop of the same list - c++

i present you my problem
I've 2 list, named them A and B.
list<vector<int> > A = {{1},{2},{3}};
list<vector<int> > B = {{4},{5},{6}};
What i want is to have A = {{1,4},{1,5},{1,6},{2,4},{2,5},{2,6},{3,4},{3,5},{3,6}} without use any tmp list.
I use C++11 with gcc 4.6.3 on Ubuntu 12.04
So that the minimize code:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),back_inserter(tmp)); // append B[j] to A[i]
A.emplace_back(tmp); //add it to A
}
}
A.erase(A_begin,A_end); // remove {1},{2},{3}
So, i think the algo is ok, but it make a infinit loop on A.
That I think is that A_end change when i make a A.emplace_back, but i save it, so i realy don't know wat append here.
my code to identify the problem:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
int ii = A.size();
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i);
A.emplace_back(tmp);
}
cout<<--ii<<endl; // exit when print 0 ?
}
This print negative number, and I've to ^C again.
EDIT : I find a solution:
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
list<vector<int>> tmp_l;
for(auto i = A_begin; i != A_end; ++i) //loop on A
{
for (auto j = B_begin;j != B_end; ++j) //loop on B
{
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),back_inserter(tmp)); // append B[j] to A[i]
tmp_l.emplace_back(move(tmp)); //add it to A
}
}
swap(tmp_l,A);

These two lines:
vector<int> tmp = (*i); // A[i]
copy((*j).begin(),(*j).end(),tmp.end()); // append B[j] to A[i]
will be invoking undefined behaviour. By copying to tmp.end() you are simply overwriting memory after the end of A[i], not extending A[i]. You need to use a back_insert iterator, something like:
vector<int> tmp = (*i); // A[i]
copy((*j).begin(), (*j).end(), back_inserter(tmp)); // append B[j] to A[i]
You'll also need to include the header to get the back_inserter.
EDIT: Also, the A_end iterator points to the position "past the end" of the list so no matter how many items you add to a they are always added in front of A_end, hence the infinite loop. I'm not sure if there's a good way to deal with this. There's no benefit here in not creating a temporary list, you are allocating the same memory either way, just write into a new list.

Your algorithm is not good.
This :
copy((*j).begin(),(*j).end(),tmp.end());
will cause all kind of problems because you overwrite some random memory.
You probably wanted to do something like this to append :
vector<int> tmp = (*i);
copy((*j).begin(),(*j).end(),std::back_inserter(tmp));

EDIT : I find a solution:
That solution is good, using a temporary vector and swapping it with A is better than doing it in place, because your original version (as well as copying past the end of the vectors) finished with an erase from the beginning which moves every element.
But your solution can be improved:
// get rid of these iterators, they're useless
/*
auto A_begin = A.begin();
auto A_end = A.end();
auto B_begin = B.begin();
auto B_end = B.end();
*/
list<vector<int>> tmp_l;
// use new for loops
for (auto& a : A)
{
for (auto& b : B)
{
// use auto
auto tmp = a; // A[i]
// I find just inserting at the end simpler than using `back_inserter`
tmp.insert(tmp.end(), b.begin(), b.end()); // append B[j] to A[i]
// then clear it the moved-from elements:
b.clear();
// move the tmp vector into place, do not copy it.
tmp_l.emplace_back(std::move(tmp));
}
}
swap(tmp_l,A);

Related

how I can assign input to map function with set in the for loop

I am wondering how I can use for loop and set for my input map!
here is what I think but there is some error!
actually I have a set Y and I want to map one element to 1 and other to zero! for example:
input: Y={2,3,4}
output: [1,0,0],[0,1,0],[0,0,1] or in other words: {2->1, 3->0, 4->0},{2->0, 3->1,4->0},{2->0,3->0,4->1}
I need my out put as a vector
for (iter = Y.begin(); iter != Y.end(); ++iter) {
Map myMap;
myMap.insert(std::make_pair(iter, 1));
if (Y != iter) {
myMap.insert(std::make_pair(Y, 0));
}
}
Note that since you've declared your map, myMap inside the for loop, you're creating an entirely new map every iteration of the loop. You also won't be able to access it outside the loop. Therefore you should declare it before the loop.
From your comment, it looks like you're trying to map all items in your set to 0 except the first. In that case, begin by mapping them all to 0, and then just change the first after:
map<int, int> m;
for(auto iter = Y.begin(); iter != Y.end(); iter++) {
m[*iter] = 0;
}
if(Y.size() != 0) {
m[*Y.begin()] = 1;
}
EDIT
As per your comments below, this should be what you're looking for:
vector<map<int,int>> v;
for(auto iter = Y.begin(); iter != Y.end(); iter++) {
map<int, int> m;
for(auto iter2 = Y.begin(); iter2 != Y.end(); iter2++) {
m[*iter2] = (*iter == *iter2);
}
v.push_back(m);
}
See it in action here
EDIT 2
After more comments, it sounds like this is what you're actually looking for:
int arr[ARR_SIZE][ARR_SIZE] = {0}; //initialize whole array to 0's
int count = 0;
for(auto iter = Y.begin(); iter != Y.end(); iter++, count++) {
arr[count][*iter-1] = 1; //pick out the specific values we want to be 1
}
(Note that I'm not sure what you mean by e, so I'm ignoring it)
See it in action here

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);

How to write a for loop that uses both an iterator and an index counter?

I have a function that looks like this:
void myclass::myfunc()
{
int i;
for( std::vector<Foo>::iterator it = var.begin(), i = 0; it < var.end(); it++, i++ )
{
/* ... */
}
}
I'm getting this error:
Cannot convert from int to std::_Vector_iterator<>
What is wrong with this code?
The issue is with this part of the for loop:
std::vector<Foo>::iterator it = var.begin(), i = 0
C++ is interpreting this not as two comma-separated statements, but as a variable declaration for a variable named it that's an iterator, and as a new declaration of a variable i that's an iterator and initialized to 0. The error is because you can't initialize a vector iterator to 0.
To fix this, you'll need to hoist the definition outside of the loop:
int i = 0;
std::vector<Foo>::iterator it = var.begin();
for(; it < var.end(); it++, i++ )
{
// ...
}
Or move the initialization of i outside the loop:
int i = 0;
for( std::vector<Foo>::iterator it = var.begin(); it < var.end(); it++, i++ )
{
// ...
}
Here's another option. If you need to keep track of the index into the vector you're currently looking at, you could consider just using a counting for loop (without the iterator), or using just the iterator and using iterator subtraction to recover the index:
for (auto it = var.begin(); it != var.end(); ++it) {
// current position is it - var.begin();
}
And, finally, if you have a C++20-compliant compiler, you could eliminate the iterator entirely and use an enhanced for loop in the following way:
/* Requires C++20 */
for (int i = 0; Foo f: var) {
/* Do something worthwhile with f. */
i++;
}
Hope this helps!
You can do it like this:
int i = 0;
for( std::vector<int>::iterator it = v.begin(); it < v.end(); ++it, ++i){}
Get rid of the i=0; part (at least inside the loop header).
Also, if you insist on doing this at all, consider using:
for (auto it : var)
or:
for (auto it = var.begin(); it != var.end(); ++it)
...instead. Since you're using a random access iterator anyway, what you have as i is equivalent to it - var.begin(). Conversely, you could just use:
for (int i=0; i<var.size(); i++)
...and get an iterator when needed as var.begin() + i.
Depending on what's in the body of the loop, you probably want to get rid of the loop entirely, and replace it with an algorithm though.
Double iteration:
using std::begin; using std::end;
for (auto p = std::make_pair( begin(var), 0 ); p.first != end(var); ++p.first, ++p.second ) {
/* ... */
}
double iteration with named indexes/iterators:
using std::begin; using std::end;
int i;
std::vector<Foo>::iterator it;
for (std::tie( it, i ) = std::make_pair( begin(var), 0 ); it != end(var); ++it, ++i ) {
/* ... */
}
or bind the above pair on each iteration to better named variables:
using std::begin; using std::end;
for (auto p = std::make_pair( begin(var), 0 ); p.first != end(var); ++p.first, ++p.second ) {
auto const& it = p.first;
int i = p.second;
}

Iterating through a set

I have a set of ints set something; of length 52.
I am using cycles to iterate through the set like this:
for(iterator A from 1st to 48th element)
for(iterator B from A+1 to 49th element)
for(iterator C from B+1 to 50th element)
for(iterator D from C+1 to 51th element)
for(iterator E from D+1 to 52th element)
{
//save the values from the actual positions in set in array[5]
}
First I tried to make it with an iterator but then I realised that it's not possible to start an iterator from the position of another iterator +1.
Then I tried to use pointers and jump through the values but I correctly assigned only the first value and then I can't jump on second etc.
My code was:
set<int> tableAll;
for(int i=4; i!=52; ++i)
tableAll.insert(i);
const int * flop1 = & * tableAll.begin();
cout << * flop1 << endl;
flop1++;
cout << * flop1 << endl;
When I cout the value of pointer flop1, I get 4 and that's ok, but when I increase it and again cout on screen, I get 0, then, 49, then 0, then 1, then 0 instead 5, 6, 7, 8 and 9.
So how to iterate through my set correctly? I assume using pointers will be faster then some iterator solution.
You absolutely can iterate from an offset from another iterator:
for (auto a(std::begin(mySet)), a_end(std::prev(std::end(mySet), 4));
a != a_end; ++a)
for (auto b(std::next(a)), b_end(std::next(a_end); b != b_end; ++b)
...
In C++03, you can write next and begin for compatibility:
template<typename Iterator> Iterator next(Iterator it, int n = 1) {
std::advance(it, n);
return it;
}
template<typename Iterator> Iterator prev(Iterator it, int n = 1) {
std::advance(it, -n);
return it;
}
for (std::set<int>::const_iterator a(mySet.begin()),
a_end(std::prev(mySet.end(), 4)); a != a_end; ++a)
for (std::set<int>::const_iterator b(std::next(a)),
b_end(std::next(a_end)); b != b_end; ++b)
...
This code is not optimal as it do unneeded iterator comparisions, but works and is simply:
set<int> tableAll;
for(int i=0; i!=52; ++i)
tableAll.insert(i);
for( set<int>::iterator iA=tableAll.begin(); iA != tableAll.end(); ++iA )
for( set<int>::iterator iB=iA; ++iB != tableAll.end(); )
for( set<int>::iterator iC=iB; ++iC != tableAll.end(); )
for( set<int>::iterator iD=iC; ++iD != tableAll.end(); )
for( set<int>::iterator iE=iD; ++iE != tableAll.end(); )
{
cout<<*iA<<' '<<*iB<<' '<<*iC<<' '<<*iD<<' '<<*iE<<endl;
}
I'd suggest to copy the set to a temporary std::vector.
All operations you do in the loops are natural for a vector and O(1) (except for the loops themselves of course)
That's easier to read, to write, and should run a lot faster.