indexing with iterators - c++

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.

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

A for loop needs to run LLONG_MAX times, but the counter variable needs to also represent signed numbers. What type do you use for the counter?

I'm hoping you can entertain this hypothetical question even though this has probably never been a problem for anyone ever.
I used to write my for loops like
for (size_t i = 0; i < container.size(); ++i)
to avoid the warnings related to comparing a signed and unsigned, but after being bitten a few too many times trying to involve i in operations that resulted in negative numbers, I started writing them like this, casting the size to int to also avoid that warning:
for (int i = 0; i < (int)container.size(); ++i)
Now lets say that there's a case where container.size() > INT_MAX and in the loop we have something like.
for (int i = 0; i < (int)container.size(); ++i) {
size_t x = 0;
while (i - x++ > INT_MIN) {
// do stuff
}
}
We need i to be signed, but we also need i to be able to represent a number larger than INT_MAX. I know that the super simple answer here to use long, but then the same problem arises eventually even if you use long long if you have to run your loop > LLONG_MAX times.
In this case, you would finally be forced into using an unsigned type for your counter variable capable of representing a number that large, but you would still need to be able to check this condition
while (i - x++ > LLONG_MIN)
how do you do it? (given you actually have some reason to run a loop 9 quintillion times).
I guess a reasonable approach would be to use some bignum library. A less reasonable, but probably more interesting approach would be to implement what's needed on your own.
Most containers have a size_type typedef to specify the data type that is used for indexes and sizes within the container. For example, if container is a std::vector, you would use std::vector::size_type instead of int or even size_t:
for (std::vector<type>::size_type i = 0; i < container.size(); ++i)
{
// use container[i] as needed
}
An alternative solution is to use iterators instead of indexes, then you don't need to worry about any counter data type at all:
for (std::vector<type>::iterator iter = container.begin(); iter != container.end(); ++iter)
{
// use *iter as needed
}
Which can be simplified using auto in C++11 and later:
for (auto iter = container.begin(); iter != container.end(); ++iter)
{
// use *iter as needed
}
Your inner while loop doesn't really make any sense to me, but if you really need something like INT_MIN for a container, you can use std::numeric_limits to get the min/max values of the container's size_type, eg:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
container_size_type x = 0;
while ((i - x++) > std::numeric_lists<container_size_type>::min()) {
// do stuff
}
}
It seems it would be easier to just loop between the two indexes instead:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
for (container_size_type j = 0; j < i; ++j) {
// do stuff
}
}
Or:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
for (container_size_type j = i; j >= 0; --j) {
// do stuff
}
}
Depending on which direction you want the inner loop to run.
However, either of those loops can be re-written using iterators as well (replace 'auto' with the appropriate type if you are not using C++11), eg:
for (auto iter = container.begin(); iter != container.end(); ++iter) {
for (auto iter2 = container.begin(); iter2 != iter; ++iter2) {
// do stuff
}
}
for (auto iter = container.begin(); iter != container.end(); ++iter) {
for (auto iter2 = std::vector<type>::reverse_iterator(iter); iter2 != container.rend(); ++iter2) {
// do stuff
}
}
If you really had a need to execute such a thing its likely that you care about the execution time because its going to take forever. At that point you have to look at something like intel's AVX, which now supports up to 512 bit numbers. In practical terms, 64 bits is almost always big enough for a loop because I seriously doubt anything that takes 2^64 (1.8e19) cycles to finish is ever going to complete in your life time because there are only about 3e18 nano seconds in a human life time.
You can use a library that can handle and compare large numbers. Or you can add another variable that will represent how many time you reached max number.
for example:
long i = 0;
long t = 0;
while (true) {
// DO your thing.
if (i >= 2000000000) {
i = 0;
++t;
if (t >= 2000000000)
break;
}
}
Or using a for loop
for (long i = 0; i < 2000000000; ++i)
for (long j = 0; j < 2000000000; ++j) {
// Do your thing
}
This way you will loop i * j times.

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

Interator and average in C++

I'm trying to learn to use iterator with vectors in C++ by, for example computing the average of a vector.
Yet this code does not give the proper answer and I cannot figure out why !
double average(vector<double> const &v)
{
vector<double>::size_type taille = v.size();
double sum = 0;
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += v[*i];
return sum/taille;
}
Can anybody give me a hint ?
Thanks a lot in advance ! Bye :)
In C++, iterators imitate the behaviors of pointers (to some degree). So if it is an iterator to an element, you access the element by dereferencing it as *it.
That means, instead of this:
sum += v[*i];
you should write this:
sum += *i; //just dereference the iterator!
Hope that helps.
Accessing vector items through an iterator is simply *i, not v[*i]. The form you've used requires accessing with index:
for (size_t i = 0; i < v.size(); i++) sum += v[i];
And your code should look like:
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += *i;
^^^^ note this
The iterator actually points to the object. Proper way to iterate is:
double average(vector<double> const &v)
{
vector<double>::size_type taille = v.size();
double sum = 0;
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += *it;
return sum/taille;
}
In C++11 you can do this too:
double average(vector<double> const &v)
{
double sum = 0;
for(const double &d : v)
sum += d;
return sum/v.size();
}

How to construct a std::list iterator in loop with increment

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)