Find all elements with the same value in a vector, then erase all of them out of the vector
Find all elements with the same value in a vector, then erase all of them out of the vector
The problem is that I need to find all elements with the same value in a vector, do something with them, then erase all of them out of the vector. Keep doing that until the vector is empty.
vector L; vector::iterator it, it2, it3; vector vec; unsigned Z; // populate the vector (1, 2, 3, 4, 2, 4) for(unsigned i = 1; i <= 4; ++i) L.push_back(i); for(unsigned i = 2; i <= 4; i = i + 2) L.push_back(i); it = L.begin(); while(it != L.end() -1){ cout<< "*it = " << *it << endl; Z=0; vec.clear(); it2 = it + 1; cout<< "*it2 = " << *it2 << endl; while(it2 != L.end()){ cout << "Loop *it2 = " << *it2 <
The output is:
*it = 1 *it2 = 2 Loop *it2 = 2 Loop *it2 = 3 Loop *it2 = 4 Loop *it2 = 2 Loop *it2 = 4
Then it stops working
If I populate the vector with this code
// populate the vector (1, 2, 3, 4, 1, 3) for(unsigned i = 1; i <= 4; ++i) L.push_back(i); for(unsigned i = 1; i <= 4; i = i + 2) L.push_back(i);
Then the output is
*it = 1 *it2 = 2 Loop *it2 = 2 Loop *it2 = 3 Loop *it2 = 4 Loop *it2 = 1 after erase(it2), *it2 = 3 Loop *it2 = 3 Z = 1 *it = 2 *it2 = 3 Loop *it2 = 3 Loop *it2 = 4 Loop *it2 = 3
It stops working here
I know there is something wrong in the second while loop but I can't figure out what it is. Any help would be appreciated.
Answer by 1201ProgramAlarm for Find all elements with the same value in a vector, then erase all of them out of the vector
The problem is with your erase
call. erase
does not automatically update the iterator; it returns the iterator to the next element. To fix it, you need to use
it2 = L.erase(it2);
and later
it = L.erase(it);
Answer by PaulMcKenzie for Find all elements with the same value in a vector, then erase all of them out of the vector
If the goal is to
- Process duplicates and then
- Erase them
there is a much easier solution to this, and that is to use std::stable_partition, along with a std::set
:
#include #include #include #include #include #include using namespace std; int main() { std::vector L = { 1, 2, 4, 3, 2, 4 }; std::set tempSet; //... // partition the elements, unique items on left, duplicates on right auto divider = stable_partition(L.begin(), L.end(), [&](int n) { // return true if item is not in the set, false otherwise return tempSet.insert(n).second; }); // do something with the duplicates, for example, print them cout << "Here are the dups:\n"; copy(divider, L.end(), ostream_iterator(cout, " ")); // get the average // get number of duplicates size_t numDups = std::distance(divider, L.end()); double avg = 0.0; // compute average using std::accumulate if ( numDups > 0 ) avg = std::accumulate(divider, L.end(), 0.0) / numDups; cout << "\nThe average of the duplicates is: " << avg << "\n"; // erase the duplicates L.erase(divider, L.end()); // print the updated vector now cout << "\n\nHere is the resulting vector:\n"; copy(L.begin(), L.end(), ostream_iterator(cout, " ")); }
Note there are no loops in the code above. Everything is done by an algorithm function. Partitioning, average computation, erasing, etc., are all performed with no loops.
Basically we test each item to see if the item exists in the set. If it does, then it will go to the right of the partition, if not, then the item goes to the left of the partition.
The return value divider
is an iterator to the element that is the "dividing line" in the partition. Once the items are partitioned, then we can process them easily by using divider
to tell us where the "good" items are and where the "about to be erased" items are.
BTW, this worked the first time I compiled it successfully -- the one major reason for this "luck" in getting it to work quickly is that the algorithm functions just plain work when given the correct parameters (and if the predicate function is written correctly). Erasing items, moving items, etc. in a container, especially a sequence container such as vector, is almost always covered by usage of 1, 2, or 3 algorithm functions.
Answer by anandnilkal for Find all elements with the same value in a vector, then erase all of them out of the vector
vector L; vector::iterator it, it2, it3; vector vec; unsigned Z; // populate the vector (1, 2, 3, 4, 2, 4) for(unsigned i = 1; i <= 4; ++i) L.push_back(i); for(unsigned i = 2; i <= 4; i = i + 2) L.push_back(i); std::set myset; for(it = L.begin(); it != L.end(); ++it){ myset.insert(*it); } for(std::set::iterator iter = myset.begin(); iter != myset.end(); ++iter){ std::cout << "element = " << *iter << std::endl; Z += *iter; } std::cout << "sum = " << Z << std::endl; Z = Z/myset.size(); std::cout<< "Average value = " << Z << std::endl; L.clear();
Answer by Sigi Schwartz for Find all elements with the same value in a vector, then erase all of them out of the vector
This is my solution, which was inspired by PaulMcKenzie's code (please don't mind my re-using some of your lines). Just like him I didn't use any handwritten loops, but made use of STL's algorithms, which one should always consider first.
In my solution I only use another container of exactly the same type and only two simple algorithms: std::remove_if
and std::find
. This way the code makes the intention a little bit clearer: find duplicates and remove them. Also note the use of std::move
that should come in handy when having a container of something more complex than int
. In that case one may have to consider using std::find_if
of course.
#include #include #include #include int main() { std::vector L = { 1, 2, 4, 3, 2, 4 }; using cont = decltype(L); using vt = cont::value_type; // find duplicates and move them to separate container cont D; D.reserve(L.size()); D.swap(L); D.erase(std::remove_if(D.begin(), D.end(), [&L] (vt& value) { if (L.cend() == std::find(L.cbegin(), L.cend(), value)) { L.emplace_back(std::move(value)); return true; } return false; }), D.end()); // do something with the duplicates, for example, print them std::cout << "Here are the dups:\n"; std::copy(D.cbegin(), D.cend(), std::ostream_iterator(std::cout, " ")); // print the vector now std::cout << "\n\nHere is the resulting vector:\n"; std::copy(L.begin(), L.end(), std::ostream_iterator(std::cout, " ")); return 0; }
See it in action here.
Answer by Thanh for Find all elements with the same value in a vector, then erase all of them out of the vector
I finally found out the solution for my own question. The question is
- We have a vector
L
that contains many duplicated elements. - We need to find all the dup elements
- Do something with the dup elements
My method is to use 2 iterators on L
, say it
and it2
. it
is kept at the beginning of L
, while it2
will go through the vector. If *it
and *it2
have the same value, then we will put *it2
into a temporary vector vec
. Then, we L.erase(it2)
. it2
will keep moving till the end of L
, collect all the dup elements into vec
and delete them from L
. When it2
reach the end of L
, we call L.erase(it)
. After that, the process continues until the vector L
is empty.
Here is the code that I modified. The most important thing to note is the condition in the while
. I use while(it < L.end())
instead of while(it != L.end())
because when we erase an element, the iterator will somehow go pass the condition !=
.
I am using an old compiler (older than C++0x) for I don't want to mess with the environment right now. Thus, it will be safe for anyone to use my code.
vector L; vector::iterator it, it2, it3, it4; vector vec; //temporary variable to store matched elements float Z; // populate the vector (1, 2, 3, 4, 1, 3) for(unsigned i = 1; i <= 4; ++i) L.push_back(i); for(unsigned i = 1; i <= 4; i = i + 2) L.push_back(i); it = L.begin(); while(it < L.end()){ cout<< "*it = " << *it << endl; Z=0; vec.clear(); if(L.size() == 1){ cout << "Last element of vector = " << *it <0) {obj0.innerHTML=s.substr(0,r);obj1.innerHTML=s.substr(r+1);}
0 comments:
Post a Comment