tags:

views:

1569

answers:

7

Is there a way to iterate over the keys, not the pairs of a C++ map?

+6  A: 

map is associative container. Hence, iterator is a pair of key,val. IF you need only keys, you can ignore the value part from the pair.

for(std::map<key,Val>::iterator iter = myMap.begin(); iter != myMap.end(); ++iter)
{
Key k =  iter->first;
//ignore value
//Value v = iter->second;
}

EDIT:: In case you want to expose only the keys to outside then you can convert the map to vector or keys and expose.

aJ
But then it will be really bad idea to expose the iterator of the vector outside.
Naveen
Do not expose the iterator. Just provide the keys in vector
aJ
+2  A: 

You want to do this?

std::map<type,type>::iterator iter = myMap.begin();
std::map<type,type>::iterator iter = myMap.end();
for(; iter != endIter; ++iter)
{
   type key = iter->first;  
   .....
}
Naveen
Yes, i know, the problem is i have a class A { public: // i'd like to expose an iterator over keys of private map here private: map<>};
Bogdan Piloca
In that case, I think you can create a std::list by using std::trasnform and picking up only the keys from the map. Then you can expose the list iterator as inserting more elements to the list will not invalidate the existing iterators.
Naveen
+9  A: 

If you really need to hide the value that the "real" iterator returns (for example because you want to use your key-iterator with standard algorithms, so that they operate on the keys instead of the pairs), then take a look at Boost's transform_iterator.

[Tip: when looking at Boost documentation for a new class, read the "examples" at the end first. You then have a sporting chance of figuring out what on earth the rest of it is talking about :-)]

Steve Jessop
Whow! Didn't know that existed!
xtofl
It's basically your first suggestion, templated to heck so as to be as general as possible.
Steve Jessop
The tip alone is worth +1
Ferruccio
+2  A: 

You could

  • create a custom iterator class, aggregating the std::map<K,V>::iterator
  • use std::transform of your map.begin() to map.end() with a boost::bind( &pair::second, _1 ) functor
  • just ignore the ->second member while iterating with a for loop.
xtofl
+1  A: 

Well, I see no actual point for your request, since


for (std::map<t1, t2>::const_iterator it = data.begin(); it != data.end(); ++it) {
        std::cout << "key = " << it->first;
}

So in other words, you can iterate over the whole map, while accessing the key via it as well.

nhaa123
"I see no actual point for your request" - do you not use algorithms at all?
Steve Jessop
I do, but the context of the question has no point since you can already iterate via the map, even tho there's the map's data-part there as well.
nhaa123
To make it more concrete: which algorithm would you use to calculate the sum of all keys in a std::map?
MSalters
MSalters: Please refer to the code-sample I gave.
nhaa123
I guess it all depends whether you interpret "how do I iterate over" in the question to mean: "how do I get iterator objects" (which could then be used with standard algorithms); or "how do I write a loop which visits" (which is what three answers here do).
Steve Jessop
onebyone: Exactly :)
nhaa123
+2  A: 

If you need an iterator that just returns the keys you need to wrap map's iterator in your own class that provides the desired interface. You can declare a new iterator class from scratch like here, of use existing helper constructs. This answer shows how to use Boost's transform_iterator to wrap the iterator in one that only returns the values/keys.

sth
+1  A: 

I know this doesn't answer your question, but one option you may want to look at is just having two vectors with the same index being "linked" information..

So in..

std::vector vName;

std::vector vNameCount;

if you want the count of names by name you just do your quick for loop over vName.size(), and when ya find it that is the index for vNameCount that you are looking for.

Sure this may not give ya all the functionality of the map, and depending may or may not be better, but it might be easier if ya don't know the keys, and shouldn't add too much processing.

Just remember when you add/delete from one you have to do it from the other or things will get crazy heh :P