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);
Related
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
I am trying to write a data structure that I can cycle round, sort of a circular list, using a vector. I resize which I am thinking should initialise the underlying array with ten elements. I don't understand why I cannot advance the iterator. Can someone please help.
I cannot use push_back() because that will always append to the end which is not what I want.
// re-use start of vector when get to end
#include <vector>
#include <iostream>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;
class printme {
public:
void operator() (int val) {cout << val << endl; }
};
//get a debug assertion - message says: vector iterators incompatible
//I assume this means that it is invalid after previous it++
int main(int argc, char* argv[])
{
vector<int> myvec;
myvec.resize(10); //underlying array now has size=10 elements
vector<int>::iterator it = myvec.begin(); //point to start of array
for(int i = 0; i < 100; ++i) {
if(it == myvec.end()) //on 2nd iteration crashes here - invalid iterator
it = myvec.begin();
myvec.insert(it++, i);
}
//print contents of vector - check 90-99 printed
for_each(myvec.begin(), myvec.end(), printme());
return 0;
}
EDIT
Changed loop to this:
for(int i = 0; i < 100; ++i) {
if(it == myvec.end())
it = myvec.begin();
*it++ = i;
}
I didn't properly understand insert.
From what you expect in output - I believe you misunderstood what insert is doing.
Implement your loop in this way (without insering - just replacing). std::vector<>::insert increments the size of your vector by one - I believe it is not what you expect.
Do not do this:
myvec.insert(it++, i);
But this:
*it++ = i;
Then you'll get your desired ouput:
//print contents of vector - check 90-99 printed
for_each(myvec.begin(), myvec.end(), printme());
Iterators can be invalidated by some operations on a vector - including insert. You'll need to re-fectch it in order to be able to use it after the insert.
vector<int>::iterator it = myvec.begin(); //point to start of array
for(int i = 0; i < 100; ++i) {
if(it == myvec.end()) //on 2nd iteration crashes here - invalid iterator
it = myvec.begin();
myvec.insert(it++, i);
//it can be invalid here, re-fetch it
it = myvec.begin();
}
I have created a vector of sets in my program, and I need to go through each of the sets. In case a specific element is found in the set, I need to add a new set to the vector. However, this gives me a segmentation fault as soon as my array's counter reaches the elements that I inserted later (within the loop). In the following code, switching on list.push_back(cS) gives me a segmentation fault.
int main(void) {
set<int> cS;
vector<set<int> > list;
cS.insert(1);
list.push_back(cS);
cS.insert(2);
list.push_back(cS);
for (int ctr = 0; ctr < list.size(); ctr++)
{
for (set<int>::iterator itr = list[ctr].begin(); itr != list[ctr].end(); itr++)
{
if (*itr == 1 || *itr == 2)
{
cS.clear();
cS.insert(3);
//list.push_back(cS);
}
}
}
for (int ctr = 0; ctr < list.size(); ctr++)
{
for (set<int>::iterator itr = list[ctr].begin(); itr != list[ctr].end(); itr++)
{
cout << *itr << endl;
}
}
return 0;
}
I would be grateful if someone could explain why this gives an error (in gcc).
Thank you for going through my post.
When you push_back into your vector you invalidate all references to elements in it in the case the vector needs to allocate more memory. In your case the iterator itr becomes invalid after the push_back. One solution would be to add the sets to a separate list (vector) and then append them all at once after the for loop:
vector<set<int> > add;
for (int ctr = 0; ctr < list.size(); ctr++)
{
for (set<int>::iterator itr = list[ctr].begin(); itr != list[ctr].end(); itr++)
{
if (*itr == 1 || *itr == 2)
{
cS.clear();
cS.insert(3);
add.push_back(cS);
}
}
}
list.insert(list.end(), add.begin(), add.end());
Is there a way that I can get the count number for an iterator?
so if at first I had this:
for (int i = 0; iter < agents.size(); ++i)
{
agents[i]->Index(i);
}
bearing in mind that Index() sets an integer, how would I do this with iterators?
for (std::vector<Agent*>::iterator iter = agents.begin(); iter < agents.end(); ++iter)
{
(*iter)->Index(????)
}
You want distance http://www.cplusplus.com/reference/std/iterator/distance/
(*iter)->Index(distance(agents.begin(),iter));
You can substract iterators:
int distance = iter - agents.begin();
EDIT:
Only works for random access iterators. (+1 internet to Let_Me_Be)
Most generally, you can always hack up something yourself:
{
int i = 0;
for (auto it = agents.begin(), end = agents.end(); it != end; ++it, ++i)
{
(*it)->set_int(i);
}
}
If you have random access iterators, you can indeed use std::distance(agents.begin(), it) safely, as has been said already.
I'm trying to do a double-loop over a std::list to operate on each pair of elements. However, I'm having some trouble initialising the second iterator. The code I'd like to write is:
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for(std::list<int>::iterator j = i+1; j != l.end(); ++j) {
...
}
}
That doesn't work because list iterators aren't random-access, so you can't do +1. But I'm having some trouble finding a neat alternative; the compiler doesn't seem to be very happy with std::list<int>::iterator j(i)++; which I had some hope for. Achieving what I want seems like I'm going to have to have some awkward extra increment which won't fit the structure of the for loop nicely.
There are obvious alternatives (using a vector, for example!) but it seems to me that there should be some reasonably neat way of doing this which I'm just not seeing at the moment.
Thanks in advance for any help :)
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j = i;
for(std::advance(j, 1); j != l.end(); ++j) {
...
}
}
How about:
for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for (std::list<int>::iterator j = i; ++j != l.end(); ) {
// ...
}
}
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j = i; ++j;
for(; j != l.end(); ++j) {
...
}
}
Back in the game!
Actually, this a pretty common idiom in numerical algorithms, so I do not see it as ugly.
I'm just going off the idea I had in dirkgently's answer:
template <typename Iter, typename Dist>
Iter advance_copy(Iter pIter, const Dist& pOffset)
{
std::advance(pIter, pOffset);
return pIter;
}
// ...
typedef std::list<int> int_list;
for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
for(int_list::iterator j = advance_copy(i, 1); j != l.end(); ++j)
{
}
}
You can make another class of utility functions too, to help make it concise:
// for consistency,
template <typename Iter>
void increment(Iter& pIter)
{
++pIter;
}
template <typename Iter>
Iter increment_copy(Iter pIter)
{
return ++pIter;
}
// ...
typedef std::list<int> int_list;
for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
for(int_list::iterator j = increment_copy(i); j != l.end(); ++j)
{
}
}
The straightforward "neat" alternative can be based on the fact that list iterator is an object of user-defined type with overloaded operators (as opposed to a built-in type). (Of course, this is not formally guaranteed, but one can expect this based on the nature of the list container.) For this reason, it is possible to apply the overloaded prefix ++ operator to a temporary object of list iterator type.
To achieve what you want you just need to create a temporary copy of i, increment it using the prefix ++ and then use the resultant value to initialize j
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for(std::list<int>::iterator j = ++std::list<int>::iterator(i); j != l.end(); ++j) {
...
}
}
And that's it. Note, that this trick is fairly popular and can be encountered in real code from time to time. Note also, that it will not generally work with std::vector because many implementations use ordinary built-in pointers as vector iterators, but it will normally work with std::list.
However, personally, I wouldn't really use this in my code. You have already received several good answers that do this by adding an extra line of code.
I'd go for Sean's suggestion, except make it a while loop:
for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j( i );
while( ++j != l.end() ) {
// ...
}
}
If you're already using Boost, then the easiest approach is to use boost::next.
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i)
for(std::list<int>::iterator j = boost::next(i); j != l.end(); ++j)